3

我想在編譯時類型的上下文/作用域中執行動態表達式(由用戶提供)。 在下面的例子中,context是任意編譯時類型的一個實例。爲了創建評估範圍,我想利用這樣一個事實,即所有可用的屬性及其類型在編譯時已知。如何獲取靜態(編譯時)類型的IDynamicMetaObjectProvider?

var engine = IronPython.Hosting.Python.CreateEngine(); 
var func = engine.CreateScriptSourceFromString("a + b").Compile(); 
var context = new { a = 1, b = 2 }; 
var scope = engine.CreateScope((IDynamicMetaObjectProvider)context); // Fails to compile 
var result = func.Execute(scope); 
context.a = 5; 
var result2 = func.Execute(scope); 

的解決方案,我不想拿的都是:

  1. 讓背景下,從DynamicObject繼承和覆蓋GetMember(由於性能原因)
  2. 添加上下文範圍和改變表達「上下文。 a + context.b「(出於可用性的原因)

我敢肯定,已經有一種獲取IDynamicMetaObjectProvider的機制,但無法弄清楚。

+0

我認爲該事件是否有產生的一類元對象提供者還是有辦法CLR類型提供了一個基本實現,提供靜態成員,這對IronPython作用域來說不是一個普遍有效的實現。對於將新變量添加到範圍的情況,它缺少動態擴展機制(類似於ExpandoObject)。或者這對你的用例是一個實際的功能? – 2012-08-07 18:26:35

+0

我只執行表達式,所以我不能在範圍內賦值或添加變量。但是謝謝你指出添加會失敗。 – Christian 2012-08-11 22:25:47

回答

0

DLR自動知道如何動態調用在編譯時定義的成員。事實上,即使你有一個實際的實現IDynamicMetaObjectProvider它會先尋找一個靜態定義的成員,然後再嘗試動態元對象。

首先,你不需要(也不能)投了plain old clr objectIDynamicMetaObjectProvider如果它實際上並沒有實現它。

其次,我認爲你的混淆,關於python作用域沒有看到你的對象的成員,來自於你使用的是Anonymous Type這一事實。 Anonymous Types被標記爲內部,因此你的python作用域沒有權限查看它的成員並且抱怨它沒有實現它。使用實際定義的對象或ExpandoObjectExpandoObjects實際上獲得會員的瘋狂真棒表現(但不設置他們),事實上他們有更好得到會員表現比plain old clr object獲得DLR

以下基準,顯示了ExpandoObject干將跑的比由DLR稱爲POCO快約43%:

public class Poco{ 
    public int One {get;set;} 
    public string Test {get;set;} 
} 

void Main() 
{ 
    var iterations =Math.Pow(10,8); 

    dynamic expando = new ExpandoObject(); 
    expando.One =1; 
    expando.Test = "Test"; 
    dynamic poco = new Poco{One =1, Test = "Test"}; 

    var stopWatch = new Stopwatch(); 
    stopWatch.Start(); 
    for(int i=0; i < iterations; i++){ 
     var test1 = poco.One; 
     var test2 = poco.Test; 
    } 
    stopWatch.Stop(); 
    var dlrPocoTime = stopWatch.ElapsedMilliseconds; 

    stopWatch = new Stopwatch(); 
    stopWatch.Start(); 
    for(int i=0; i < iterations; i++){ 
     var test1 = expando.One; 
     var test2 = expando.Test; 
    } 
    stopWatch.Stop(); 
    var expandoTime = stopWatch.ElapsedMilliseconds; 


    Console.WriteLine((double)dlrPocoTime/expandoTime); 

} 
+0

我知道我無法將poco投射到idmop(編譯器告訴我:-),但我的問題是如何實施poco的idmop。匿名類型僅用於示例中。我也可以使用真正的類型。 – Christian 2012-08-11 22:33:04

+0

對於ExpandoObject和poco之間的性能比較,您是否有一些鏈接或基準? – Christian 2012-08-11 22:36:25

+0

您並未實現一個IDMOP,其中所有成員在編譯時都知道,DLR不需要DynamicMetaObject就可以調用非動態成員。我還添加了一個可以運行的基準。在我的機器上,DLR對ExpandoObject上的getter的調用比DLR對poco對象的調用快43%。 – jbtule 2012-08-13 13:44:47