質問

の違いは何ですか System.Dynamic.ExpandoObject, System.Dynamic.DynamicObjectdynamic?

これらのタイプはどの状況で使用していますか?

役に立ちましたか?

解決

dynamic キーワードは、遅刻する必要がある変数を宣言するために使用されます。
実際のまたは想像上のタイプに対して、遅いバインディングを使用したい場合は、 dynamic キーワードとコンパイラは残りを行います。

使用するとき dynamic 通常のインスタンスと対話するためのキーワード DLR インスタンスの通常の方法に後期の呼び出しを実行します。

IDynamicMetaObjectProvider インターフェース クラスが遅れた動作を制御できるようにします。
使用するとき dynamic と対話するためのキーワード IDynamicMetaObjectProvider 実装では、DLRが呼び出します IDynamicMetaObjectProvider 方法とオブジェクト自体は、何をすべきかを決定します。

ExpandoObjectDynamicObject クラスはの実装です IDynamicMetaObjectProvider.

ExpandoObject メンバーをインスタンスに追加して使用できるシンプルなクラスです dynamic味方。
DynamicObject カスタマイズされた動作を簡単に提供するために継承できるより高度な実装です。

他のヒント

私はこの質問に対するより明確な答えを提供しようとします。 ExpandoObjectDynamicObject.

非常に迅速に、 dynamic dynamic この答えの残りの部分で。

ExpandoObjectDynamicObject 確かにタイプです。表面的には、彼らは互いに非常によく似ています。両方のクラスが実装します IDynamicMetaObjectProvider. 。ただし、深く掘り下げると、それらはまったく似ていないことがわかります。

DynamicObjectは、の部分的な実装です IDynamicMetaObjectProvider 純粋に、開発者がカスタムの基礎となるストレージと検索動作を使用して動的なディスパッチをサポートする独自のカスタムタイプを実装して、動的ディスパッチを機能させることを意図しています。

  1. DynamicObjectは直接構築できません。
  2. DynamicObjectを開発者として使用するには、DynamicObjectを拡張する必要があります。
  3. DynamicObjectを拡張すると、実行時に基礎となるデータ表現に内部に保存されているデータにダイナミックディスパッチを解決する方法に関するカスタム動作を提供できるようになりました。
  4. ExpandOObjectは、辞書などに基礎となるデータを保存します。DynamicObjectを実装すると、どこにでもデータを保存できます。 (たとえば、ディスパッチのデータを取得して設定する方法は完全にあなた次第です)。

要するに、DLRで使用できる独自のタイプを作成し、必要なカスタム動作を使用して作業する場合は、DynamicObjectを使用します。

例:存在しないメンバーで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 おそらくあなたのために働く特定の動的ディスパッチ行動を使用して、DynamicObjectを拡張するための事前に選択された方法の1つです, 、しかし、特定のニーズに依存しない場合があります。

一方、 DyanmicObject ユニークな動的動作を備えた独自のタイプをシンプルで簡単に実装するヘルパーベースタイプです。

上記の例の多くのソースが基づいている便利なチュートリアル。

C#言語仕様に応じて dynamic タイプ宣言です。すなわち dynamic x 変数を意味します x タイプがあります dynamic.

DynamicObject 実装が簡単になるタイプです IDynamicMetaObjectProvider したがって、タイプの特定の結合挙動をオーバーライドします。

ExpandoObject プロパティバッグのように機能するタイプです。つまり、実行時にこのタイプの動的インスタンスにプロパティ、メソッドなどを追加できます。

上記の例 DynamicObject 既に提供されている機能を基本的に実装しているため、違いを明確に伝えません。 ExpandoObject.

以下の2つのリンクでは、 DynamicObject, 、実際のタイプを保存/変更することが可能です(XElement 以下のリンクで使用されている例)およびプロパティとメソッドのより良い制御。

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

https://blogs.msdn.microsoft.com/csharpfaq/2009/10/19/dynamic-in-c-4-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