没有IDynamicMetaObject的c#动态?

时间:2012-05-05 20:29:22

标签: c# .net dynamic clr

  

对象可以通过实现提供其绑定语义   IDynamicMetaObject Provider - 或者更容易通过子类化   DynamicObject,提供此的默认实现   接口

source

我从未实现此接口或类,并且始终能够动态执行:

public class aa
    {
        public void bbb()
        {  }
    }

dynamic a = new aa().bbb();

所以这句话是什么意思?

我试图了解何时需要使用IDynamicMetaObject或DynamicObject继承

2 个答案:

答案 0 :(得分:2)

dynamic关键字导致对对象的引用是后期绑定的,并且仅在运行时解析。通常,原因是因为您使用的是IDynamicMetaObjectProvider实现者​​,它允许您的代码决定如何处理运行时属性解析。也就是说,您可能希望在运行时添加和删除属性(通常实现为字典,如ExpandoObject)。

您的示例代码正在做的只是阻止编译类型检查。实际上它比什么都不做更糟糕,因为如果你编写的代码访问了类的不存在的属性或方法,它仍然会编译,但当然会在运行时崩溃。我想不出有很多很好的理由来引用具有dynamic的具体类(期望使用简洁的类型转换或鸭子类型,但我们通常在C#中使用类似这样的接口!)

从我自己的一个项目继承DynamicObject的动态对象的示例实现:

https://github.com/jamietre/IQObjectMapper/blob/master/source/IQObjectMapper/IQDynamicObject.cs

(它调用一个返回带有选项的新字典的工厂方法,所有你需要做的就是改变构造函数:

InnerDict = ObjectMapper.MapperCache.GetDictionary<object>(Options);

为:

InnerDict = new Dictionary<string,object>();

并摆脱一些检查选项的条件

答案 1 :(得分:0)

我讨厌给出这样的“精辟”答案,因为它不是非常具有影响力,但这确实是“如果你需要它,你就会知道。”

您需要在应用程序中实现动态对象,甚至大多数库代码都是非常罕见的。该接口适用于实现只能 用作动态对象的类的人员;例如,如果您想在对象上实现类似Javascript的行为。您可以在这样的对象上调用所需的任何属性或方法,它将进行编译。这取决于您在运行时的实现,以确定给定的调用是否有效。

一个完全没有意义但描述性的例子是根据星期几决定哪些属性有效的类:

public class WeekendObject : DynamicObject
{
  Dictionary<string, object> propertybag = new Dictionary<string, object>();      

  public override bool TryGetMember(GetMemberBinder binder, out object result)
  {
    if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
    {
      if (name.StartsWith("Sunday"))
      {
        return propertybag.TryGetValue(name, out result);
      }
    }
    else
    {
      if (!name.StartsWith("Sunday"))
      {
        return propertybag.TryGetValue(name, out result);
      }
    }
  }

  public override bool TrySetMember(SetMemberBinder binder, object value)
  {
    if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
    {
      if (name.StartsWith("Sunday"))
      {
        propertybag[binder.Name.ToLower()] = value;
        return true;
      }
    }
    else
    {
      if (!name.StartsWith("Sunday"))
      {
        propertybag[binder.Name.ToLower()] = value;
        return true;
      }
    }

    return false;
  }
}