web-dev-qa-db-ja.com

動的オブジェクトのメンバーをどのように反映しますか?

.NET 4のdynamicキーワードで宣言されたオブジェクトからプロパティとその値の辞書を取得する必要がありますか?これにリフレクションを使用すると機能しないようです。

例:

dynamic s = new ExpandoObject();
s.Path = "/Home";
s.Name = "Home";

// How do I enumerate the Path and Name properties and get their values?
IDictionary<string, object> propertyValues = ???
122
Flatliner DOA

IDynamicMetaObjectProviderが動的メンバー名を提供できる場合、それらを取得できます。 GetMemberNames ApacheライセンスPCLライブラリでの実装を参照してください Dynamitey (nugetにあります)、ExpandoObjectsおよびDynamicObjectsに対して実装されますGetDynamicMemberNamesおよびその他のIDynamicMetaObjectProviderは、is IDynamicMetaObjectProviderを超えるカスタムテストなしでGetDynamicMemberNamesの実装をメタオブジェクトに提供します。

メンバー名を取得した後、値を正しい方法で取得するのは少し手間がかかりますが、Impromptuはこれを行いますが、興味深い部分だけを指し示して意味を持たせることは困難です。 ドキュメント であり、リフレクションと同等またはそれより高速ですが、expandoの辞書検索よりも高速ではない可能性がありますが、expando、dynamicまたはoriginalのオブジェクトに対して機能します-名前を付けます。

30
jbtule

ExpandoObjectの場合、ExpandoObjectクラスは実際にそのプロパティにIDictionary<string, object>を実装するため、ソリューションはキャストと同じくらい簡単です。

IDictionary<string, object> propertyValues = (IDictionary<string, object>)s;

これは一般的な動的オブジェクトでは機能しないことに注意してください。これらの場合、IDynamicMetaObjectProviderを介してDLRにドロップダウンする必要があります。

98
itowlson

考慮すべきいくつかのシナリオがあります。まず、オブジェクトのタイプを確認する必要があります。このために、単にGetType()を呼び出すことができます。タイプがIDynamicMetaObjectProviderを実装していない場合、他のオブジェクトと同じリフレクションを使用できます。何かのようなもの:

var propertyInfo = test.GetType().GetProperties();

ただし、IDynamicMetaObjectProvider実装の場合、単純なリフレクションは機能しません。基本的に、このオブジェクトについてもっと知る必要があります。 ExpandoObject(IDynamicMetaObjectProvider実装の1つ)である場合、itowlsonが提供する回答を使用できます。 ExpandoObjectはそのプロパティをディクショナリに保存し、動的オブジェクトをディクショナリにキャストするだけです。

DynamicObject(別のIDynamicMetaObjectProvider実装)の場合、このDynamicObjectが公開するメソッドを使用する必要があります。 DynamicObjectは、プロパティのリストをどこにでも実際に「保存」する必要はありません。たとえば、次のようになります( my blog post の例を再利用しています):

public class SampleObject : DynamicObject
{
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = binder.Name;
        return true;
    }
}

この場合、(任意の名前で)プロパティにアクセスしようとすると、オブジェクトは単にプロパティの名前を文字列として返します。

dynamic obj = new SampleObject();
Console.WriteLine(obj.SampleProperty);
//Prints "SampleProperty".

したがって、何も反映する必要はありません。このオブジェクトにはプロパティがなく、同時にすべての有効なプロパティ名が機能します。

IDynamicMetaObjectProvider実装の場合、ExpandoObjectなどのプロパティのリストを取得し、残りは無視(または例外をスロー)できる既知の実装でフィルタリングする必要があります。

57

Newtonsoft Json.Netが必要

少し遅れましたが、私はこれを思いつきました。それはあなただけのキーを提供し、それからあなたはダイナミックでそれらを使用することができます:

public List<string> GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor)
{
    JObject attributesAsJObject = dynamicToGetPropertiesFor;
    Dictionary<string, object> values = attributesAsJObject.ToObject<Dictionary<string, object>>();
    List<string> toReturn = new List<string>();
    foreach (string key in values.Keys)
    {
        toReturn.Add(key);                
    }
    return toReturn;
}

次に、このように単にforeachします:

foreach(string propertyName in GetPropertyKeysForDynamic(dynamicToGetPropertiesFor))
{
    dynamic/object/string propertyValue = dynamicToGetPropertiesFor[propertyName];
    // And
    dynamicToGetPropertiesFor[propertyName] = "Your Value"; // Or an object value
}

値を文字列または他のオブジェクトとして取得するか、別の動的な操作を実行してルックアップを再度使用することを選択します。

17
Mr. B