有什么区别 System.Dynamic.ExpandoObject, System.Dynamic.DynamicObjectdynamic?

在哪种情况下,您使用这些类型?

有帮助吗?

解决方案

dynamic 关键字用于声明应该是后期的变量。
如果要使用较晚的绑定,对于任何真实或想象中的类型,则使用 dynamic 关键字和编译器将完成其余的工作。

当您使用 dynamic 与普通实例互动的关键字, DLR 执行对实例普通方法的后期呼叫。

IDynamicMetaObjectProvider 界面 允许班级控制其后期行为。
当您使用 dynamic 与一个关键字交互 IDynamicMetaObjectProvider 实施,DLR调用 IDynamicMetaObjectProvider 方法和对象本身决定该怎么做。

ExpandoObjectDynamicObject 课程是实现 IDynamicMetaObjectProvider.

ExpandoObject 是一个简单的类,使您可以将成员添加到实例并使用它们 dynamic盟友。
DynamicObject 是一个更高级的实现,可以继承以轻松提供自定义行为。

其他提示

我将尝试为这个问题提供更清晰的答案,以清楚地解释动态之间的区别 ExpandoObjectDynamicObject.

很快, dynamic 是关键字。它不是per-se类型。这是一个关键字,它告诉编译器在设计时间时忽略静态检查,而不是在运行时使用后期结合。因此,我们不会花很多时间 dynamic 在此答案的其余部分。

ExpandoObjectDynamicObject 确实是类型。从表面上看,它们看起来彼此非常相似。两个类都实现 IDynamicMetaObjectProvider. 。但是,挖掘更深入,您会发现它们一点也不相似。

DynamicObject是部分实现 IDynamicMetaObjectProvider 纯粹是要成为开发人员实施自己的自定义类型的起点,以自定义的基础存储和检索行为支持动态调度,以使动态调度工作。

  1. 动态对象不能直接构造。
  2. 您必须扩展DynamicObject,以使其作为开发人员有用。
  3. 当您扩展DynamicObject时,您现在可以提供有关如何在运行时内部内部存储在内部存储的数据的自定义行为。
  4. explionObject存储在字典中等等。 (例如,您如何获得和设置Dispatch的数据完全取决于您)。

简而言之,当您想创建自己的类型时,请使用DynamicObject,可以与DLR一起使用,并与您想要的任何自定义行为一起使用。

示例:想象一下,您想拥有一个动态类型,该类型每当尝试在不存在的成员身上尝试get时返回自定义默认值(即未在运行时添加)。默认会说:“对不起,这个罐子里没有饼干!”。如果您想要这样的动态对象,则需要控制找不到字段时发生的事情。 ExpandOobject不会让您这样做。因此,您需要使用独特的动态成员分辨率(调度)行为来创建自己的类型,并使用该类型而不是现成的 ExpandoObject.

您可以创建类型如下:(注意,以下代码仅用于插图,可能不会运行。要了解如何正确使用DynamicObject,其他地方有许多文章和教程。)

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

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (properties.ContainsKey(binder.Name))
        {
            result = properties[binder.Name];
            return true;
        }
        else
        {
            result = "I'm sorry, there are no cookies in this jar!"; //<-- THIS IS OUR 
            CUSTOM "NO COOKIES IN THE JAR" RESPONSE FROM OUR DYNAMIC TYPE WHEN AN UNKNOWN FIELD IS ACCESSED
            return false;
        }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        properties[binder.Name] = value;
        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        dynamic method = properties[binder.Name];
        result = method(args[0].ToString(), args[1].ToString());
        return true;
    }
}

现在,我们可以使用我们刚刚创建的这个虚构类作为动态类型,如果该字段不存在,则具有非常自定义的行为。

dynamic d = new MyNoCookiesInTheJarDynamicObject();
var s = d.FieldThatDoesntExist;

//in our contrived example, the below should evaluate to true
Assert.IsTrue(s == "I'm sorry, there are no cookies in this jar!")

ExpandoObject 是完整的实施 IDynamicMetaObjectProvider, ,.NET框架团队为您做出了所有这些决定。如果您不需要任何自定义行为,这将很有用,并且您认为ExpandOobject对您来说足够好(90%的时间, ExpandoObject 足够好)。因此,例如,请参见以下内容,对于ExpandOobject,设计人员选择如果不存在动态成员,则选择异常。

dynamic d = new ExpandoObject();

/*
The ExpandoObject designers chose that this operation should result in an 
Exception. They did not have to make that choice, null could 
have been returned, for example; or the designers could've returned a "sorry no cookies in the jar" response like in our custom class. However, if you choose to use 
ExpandoObject, you have chosen to go with their particular implementation 
of DynamicObject behavior.
*/

try {
var s = d.FieldThatDoesntExist;
}
catch(RuntimeBinderException) { ... }

因此总结, ExpandoObject 只是一种使用某些动态调度行为扩展动态对象的预选方法,这些行为可能对您有用, ,但可能不会取决于您的特定需求。

然而, DyanmicObject 是一种辅助木材,它使自己的类型具有独特的动态行为,简单简便。

上述许多示例源基于的有用教程。

根据C#语言规范 dynamic 是类型声明。 IE dynamic x 表示变量 x 有类型 dynamic.

DynamicObject 是一种使其易于实施的类型 IDynamicMetaObjectProvider 因此,该类型覆盖了特定的结合行为。

ExpandoObject 是一种像财产包一样起作用的类型。即,您可以在运行时将属性,方法等添加到此类型的动态实例中。

上面的示例 DynamicObject 不能清楚地说明差异,因为它基本上是在实现已提供的功能 ExpandoObject.

在下面提到的两个链接中,很明显,在 DynamicObject, ,可以保留/更改实际类型(XElement 在以下链接中使用的示例中)和更好地控制属性和方法。

https://blogs.msdn.microsoft.com/csharpfaq/2009/09/30/dynamic-in-c-4-0-indroducing-the-the-poducing-the-expandoobject/

https://blogs.msdn.microsoft.com/csharpfaq/2009/10/10/19/dynamic-in-c-4-0-0-0-creating-wrappers-with-dynamicobject/

public class DynamicXMLNode : DynamicObject    
{    
    XElement node;

    public DynamicXMLNode(XElement node)    
    {    
        this.node = node;    
    }

    public DynamicXMLNode()    
    {    
    }

    public DynamicXMLNode(String name)    
    {    
        node = new XElement(name);    
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)    
    {    
        XElement setNode = node.Element(binder.Name);

        if (setNode != null)    
            setNode.SetValue(value);    
        else    
        {    
            if (value.GetType() == typeof(DynamicXMLNode))    
                node.Add(new XElement(binder.Name));    
            else    
                node.Add(new XElement(binder.Name, value));    
        }

        return true;    
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)    
    {    
        XElement getNode = node.Element(binder.Name);

        if (getNode != null)    
        {    
            result = new DynamicXMLNode(getNode);    
            return true;    
        }    
        else    
        {    
            result = null;    
            return false;    
        }    
    }    
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top