2

一个对象可以通过实现 IDynamicMetaObject Provider 来提供它的绑定语义,或者更容易地通过继承 DynamicObject 来提供这个接口的默认实现。

来源

我从来没有实现过这个接口和类,并且总是能够动态地执行事情:

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

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

那么这句话是什么意思呢?

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

4

2 回答 2

2

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

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

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

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

(它调用了一个工厂方法,该方法返回一个带有选项的新字典,您需要做的就是使这个非依赖项改变构造函数:

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

到:

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

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

于 2012-05-05T20:32:59.583 回答
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;
  }
}
于 2012-05-05T20:58:10.863 回答