2012-11-27 1162 views
2

自從開始使用Dart以來,我一直在觀察如何執行Dart(文本)源代碼(即可以動態生成相同的程序)作爲代碼。像臭名昭着的「eval()」函數。如何在Dart中動態執行(如Eval)?

最近我收到了一些提示,Isolates之間的通信端口支持某種似乎可以允許這種「技巧」的「產卵」。在Ruby中,也可以動態地將模塊作爲語言功能加載,也許在Dart中有一些方法可以做到這一點?

任何線索或簡單的例子將不勝感激。

在此先感謝!

回答

8

拉吉斯拉夫吞提供這個答案(上達特論壇),

我認爲這是非常肯定地說,達特將永遠不會有EVAL。但它會有其他更動態生成代碼的結構化方式(代碼名稱鏡像構建器)。雖然現在沒有這樣的事情。

有兩種產生隔離的方法:spawnFunction,它從一個新隔離中的現有代碼運行一個現有函數,所以你沒有找到任何東西,以及spawnUri,它從給定的URI下載代碼並在新的代碼中運行它隔離。這本質上是動態代碼加載 - 但動態加載的代碼與現有代碼隔離。它運行在一個新的隔離區中,所以與它通信的唯一方法是通過消息傳遞(通過端口)。

謝謝拉吉斯拉夫...

+0

[鏈接](https://groups.google.com/a/dartlang.org/forum /?fromgroups =#!話題/其它/ 3FREqBwn5ok)。另請參閱[常見問題解答](http://www.dartlang.org/support/faq.html#is-it-a-dynamic-language)。 – tjameson

0

的eval(),在Ruby中,至少,可以執行從單一的語句(如賦值),到完全的參與程序。對於大多數可能的其他任何形式的執行,執行許多小片段都有相當大的時間限制。

仔細觀察問題,至少有三種不同的功能,這些功能位於可以使用eval的各種方案的基礎上。 Dart至少以最少的方式處理其中的2個。

Dart沒有,也沒有任何計劃支持「通用」腳本執行。

但是,可以使用NoSuchMethod方法來有效地實現向本地類環境中動態「注入」變量。它用一個看起來像這樣的字符串替換eval():eval(「String text ='your name here';」);現在Dart現在支持的第二個函數是方法的調用,它看起來像這樣:eval(「Map map = SomeClass.some_method()」);

經過與此有關後,它終於明白了我可以使用一個簡單的類來存儲調用一個方法所需的信息,對於一個類來說,這個類似於具有一般效用的字符串。我可以替換一個大的易於維護的switch語句,否則可能需要調用一系列方法。在Ruby中,這幾乎是微不足道的,但是在Dart中,有一些不太直觀的調用,所以我想在一個地方得到這個「技巧」,這將適合於對字符串進行排序和過濾,比如你可能需要的。

下面是使用反射將多個類(整個庫?)「積累」到地圖中的代碼,以便只使用一個鍵(作爲字符串)就可以調用class.methodName()。

注:我使用了幾個「幫手法」來做Map &列表函數,你可能會想用直鏢代替它們。然而,這種碼被使用和測試僅使用函數..

下面的代碼:

//The used "Helpers" here.. 
MAP_add(var map, var key, var value){ if(key != null){map[key] = value;}return(map);} 
Object MAP_fetch(var map, var key, [var dflt = null]) {var value = map[key];if (value==null) {value = dflt;}return(value);} 


class ClassMethodMapper { 
    Map _helperMirrorsMap, _methodMap; 

    void accum_class_map(Object myClass){ 
    InstanceMirror helperMirror = reflect(myClass); 
    List methodsAr = helperMirror.type.methods.values; 
    String classNm = myClass.toString().split("'")[1]; ///#FRAGILE  
    MAP_add(_helperMirrorsMap, classNm, helperMirror); 
    methodsAr.forEach((method) { 
     String key = method.simpleName; 
     if (key.charCodeAt(0) != 95) { //Ignore private methods 
     MAP_add(_methodMap, "${classNm}.${key}()", method); 
     } 
    }); 
    } 

    Map invoker(String methodNm) { 
    var method = MAP_fetch(_methodMap, methodNm, null); 
    if (method != null) {   
     String classNm = methodNm.split('.')[0];   
     InstanceMirror helperMirror = MAP_fetch(_helperMirrorsMap, classNm); 
     helperMirror.invoke(method.simpleName, []); 
    } 
    } 

    ClassMethodMapper() { 
    _methodMap   = {}; 
    _helperMirrorsMap = {}; 
    } 
}//END_OF_CLASS(ClassMethodMapper); 


============ 

main() { 
    ClassMethodMapper cMM = new ClassMethodMapper(); 
    cMM.accum_class_map(MyFirstExampleClass); 
    cMM.accum_class_map(MySecondExampleClass); 

    //Now you're ready to execute any method (not private as per a special line of code above) 
    //by simply doing this: 
    cMM.invoker(MyFirstExampleClass.my_example_method()); 
}