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