.NET 4に追加されている ExpandoObject クラスを使用すると、実行時にオブジェクトにプロパティを任意に設定できます。
Dictionary<string, object>
、あるいは実際には Hashtable を使用するよりも、これに利点はありますか?私が言うことができる限り、これはあなたがもう少し簡潔な構文でアクセスできるハッシュテーブルに他なりません。
たとえば、これはなぜでしょうか。
dynamic obj = new ExpandoObject();
obj.MyInt = 3;
obj.MyString = "Foo";
Console.WriteLine(obj.MyString);
次のものよりも、本当に優れているか、大幅に異なります。
var obj = new Dictionary<string, object>();
obj["MyInt"] = 3;
obj["MyString"] = "Foo";
Console.WriteLine(obj["MyString"]);
どんな本当の利点は、単に任意の辞書型を使う代わりにExpandoObjectを使うことによって得られます実行時に決定されます。
私があなたが言及しているMSDNの記事を書いたので、私はこれに答えなければならないと思います。
最初に、私はこの質問を予想しました、そしてそれが私がExpandoObjectのための多少実際のユースケースを示すブログ記事を書いた理由です: C#4.0の動的:ExpandoObjectの紹介 .
まもなく、ExpandoObjectは複雑な階層オブジェクトを作成するのに役立ちます。たとえば、辞書の中に辞書があるとします。
Dictionary<String, object> dict = new Dictionary<string, object>();
Dictionary<String, object> address = new Dictionary<string,object>();
dict["Address"] = address;
address["State"] = "WA";
Console.WriteLine(((Dictionary<string,object>)dict["Address"])["State"]);
階層が深ければ深いほど、コードはそれだけ大きくなります。 ExpandoObjectを使えば、エレガントで読みやすくなります。
dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);
第二に、すでに指摘したように、ExpandoObjectはINotifyPropertyChangedインターフェースを実装しているので、辞書よりもプロパティをより細かく制御できます。
最後に、次のようにExpandoObjectにイベントを追加できます。
class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
// Initialize the event to null (meaning no handlers)
d.MyEvent = null;
// Add some handlers
d.MyEvent += new EventHandler(OnMyEvent);
d.MyEvent += new EventHandler(OnMyEvent2);
// Fire the event
EventHandler e = d.MyEvent;
if (e != null)
{
e(d, new EventArgs());
}
// We could also fire it with...
// d.MyEvent(d, new EventArgs());
// ...if we knew for sure that the event is non-null.
}
static void OnMyEvent(object sender, EventArgs e)
{
Console.WriteLine("OnMyEvent fired by: {0}", sender);
}
static void OnMyEvent2(object sender, EventArgs e)
{
Console.WriteLine("OnMyEvent2 fired by: {0}", sender);
}
}
1つの利点は、シナリオを拘束することです。データグリッドとプロパティグリッドはTypeDescriptorシステムを介して動的プロパティを取得します。さらに、WPFデータバインディングは動的プロパティを理解するため、WPFコントロールは辞書よりも容易にExpandoObjectにバインドできます。
辞書エントリではなくDLRプロパティを期待する動的言語との相互運用性も、一部のシナリオでは考慮事項になる場合があります。
私にとって本当の利点は、XAMLからの完全に楽なデータバインディングです。
public dynamic SomeData { get; set; }
...
SomeData.WhatEver = "Yo Man!";
...
<TextBlock Text="{Binding SomeData.WhatEver}" />
DLR
を基盤とした他の言語との相互運用性が私が考えることができる一番の理由です。 IDynamicMetaObjectProvider
ではなく、Dictionary<string, object>
を渡すことはできません。もう1つの追加された利点は、それがINotifyPropertyChanged
を実装することです。これはWPFのデータバインディングの世界ではDictionary<K,V>
が提供できるものを超えた追加の利点も持つことを意味します。
プログラマーの利便性に関するすべてです。このオブジェクトを使って素早く汚いプログラムを書くことを想像することができます。
辞書を使用して動的に追加されたプロパティを「偽造」することはもうないので、構文上の利点があると思います。
それ、そして動的言語と相互運用すると私は思います。
それは、入ってくる構造化データ(つまりXML、Json)のための動的なアドホック型を作成するためのExpandoObjectの使用についての MSDNの記事 からの例です。
ExpandoObjectの動的プロパティにデリゲートを代入することもできます。
dynamic person = new ExpandoObject();
person.FirstName = "Dino";
person.LastName = "Esposito";
person.GetFullName = (Func<String>)(() => {
return String.Format("{0}, {1}",
person.LastName, person.FirstName);
});
var name = person.GetFullName();
Console.WriteLine(name);
したがって、実行時に動的オブジェクトにロジックを挿入することができます。したがって、ラムダ式、クロージャ、動的キーワード、 DynamicObjectクラス とともに、JavaScriptやPHPのような動的言語から知っている関数型プログラミングの要素をC#コードに取り入れることができます。 。
これが便利な場合がいくつかあります。たとえば、モジュール化シェルに使用します。各モジュールは、その設定にバインドされた独自の設定ダイアログデータを定義します。私はそれをDatacontextとしてExpandoObjectで提供し、私の設定Storageに値を保存します。このようにして、設定ダイアログの作成者は値にバインドするだけで、自動的に作成および保存されます。 (そしてもちろんこれらの設定を使うためにモジュールに提供されます)
それは単に辞書よりも使いやすいです。しかし、誰もが内部的にそれは単なる辞書であることを知っておくべきです。
LINQは単なる構文上の糖のようなものですが、時には物事を楽にします。
それであなたの質問に直接答えるために:それは書くことと読むことがより簡単です。しかし技術的には本質的にDictionary<string,object>
です(値をリストするためにそれを1つにキャストすることさえ可能です)。