C#中DynamicMetaObject的Binder缓存配置

时间:2011-12-22 13:18:42

标签: c# .net dynamic-language-runtime

我在C#中执行IDynamicMetaObjectProvider的自定义实现,因为我需要比使用DynamicObject更好的性能,并且我需要继承。我使用DynamicMetaObjectBindSetMember的自定义实现扩展BindGetMember。我的问题是:

何时调用BindSetMember和BindGetMember以及何时使用缓存规则?即,什么是缓存配置?

从调试我的实现我理解,例如,为每个特定的BindSetMember类,属性名称和参数类型调用IDynamicMetaObjectProvider。但我还没有找到任何这方面的文件。此外,在下面的代码中BindSetMember被调用两次,BindGetMember被调用两次,而我希望每个被调用一次:

dynamic obj = new MyDynamicImplementation();
obj.Property = 0; // Calls BindSetMember
if (obj.Property != 0) {} // Calls BindGetMember
obj.Property++; // Calls BindGetMember, then BindSetMember

有人可以解释或提及解释上述问题的文件吗?

1 个答案:

答案 0 :(得分:1)

一个简单而高级的解释是缓存是按类型和每个调用站点完成的。在上面的示例中,呼叫站点对应于代码行。因此,缓存不用于任何行。

使用缓存的一个示例是访问循环中的属性,例如:

for (int i = 0; i < 10; i++)
    obj.Property = i;

在上面的示例中,绑定将在i = 0时完成一次,然后缓存将用于接下来的9次调用。

使用缓存的更复杂的例子:

public class Class1 : MyDynamicImpelementation {}
public class Class2 : MyDynamicImpelementation {}

static class Class
{
    public void PropertyAccess(dynamic obj)
    {
        for (int i = 0; i < 10; i++)
            obj.Property = i;
    }

    public void Main(string[] args)
    {
        PropertyAccess(new Class1());
        PropertyAccess(new Class2());
    }
}

在上面的示例中,obj类型Class1i = 0的绑定只会执行一次,然后缓存将用于其余的循环调用和{{ 1}}类型obj和任何Class2

作为结论: 如果从不同代码行访问的属性或值的类型不同,则会调用iBindGetMethod