web-dev-qa-db-ja.com

動的オブジェクトをExpandoObjectに変換できますか(c#)

ドライバーAPI(dll内)から「SealedClass」タイプの動的オブジェクトを取得しています。このオブジェクトをいくつかの追加プロパティで装飾したいと思います。

私は次のようなことをしたいと思います:

public void expandIT(dynamic sealedObject) {

    ExpandoObject expand = new ExpandoObject(sealedObject);
    expand.time = DateTime.Now();
    etc....
}

[〜#〜] update [〜#〜]

JCLのソリューションが好きです。しかし、私がやりたかったこととしては、ExpandoObjectを作成し、Dynamicの封印されたクラスオブジェクトを子プロパティとして埋め込み、プロパティを親のExpandoObjectに追加する方が簡単でした。 JCLのおかげで、私はこれを行う方法について頭がおかしくなりました。私

10
Dr.YSG

いいえ。 dynamicオブジェクトは、コンパイル時に型を強制しませんが、オブジェクトを魔法のように拡張可能にすることはありません(ExpandoObjectでない限り)。

ただし、DynamicObject...を使用して、次のようなラッパーまたはプロキシを作成できます。

public class ExpandedObjectFromApi : DynamicObject
{
    private Dictionary<string, object> _customProperties = new Dictionary<string, object>();
    private object _currentObject;

    public ExpandedObjectFromApi(dynamic sealedObject)
    {
      _currentObject = sealedObject;
    }

    private PropertyInfo GetPropertyInfo(string propertyName) 
    { 
       return _currentObject.GetType().GetProperty(propertyName);
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
      var prop = GetPropertyInfo(binder.Name);
      if(prop != null)
      {
         result = prop.GetValue(_currentObject);
         return true;
      }
      result = _customProperties[binder.Name];
      return true;          
    }      

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
      var prop = GetPropertyInfo(binder.Name);
      if(prop != null)
      {
         prop.SetValue(_currentObject, value);
         return true;
      }
      if(_customProperties.ContainsKey(binder.Name))
        _customProperties[binder.Name] = value;
      else
        _customProperties.Add(binder.Name, value);
      return true;          
    }      
}

そして、次のように使用できます。

dynamic myExpandedObject = new ExpandedObjectFromApi(sealedObject);

これにより、元のオブジェクトのプロパティが見つかった場合は返されます。元のオブジェクトにその名前のプロパティがない場合は、「カスタム」プロパティとして追加されます。

スタックオーバーフローエディタでコードを作成しましたが、おそらく多くの間違いを犯しました。コピー/貼り付けには適しておらず、大量のエラーチェックが必要です(受信したオブジェクトにフィールドとメソッドがある場合は、それらも実装する必要があります) 。基本的な考え方がわかるように書いただけです。

また、特別なプロパティ(たとえば、WrappedObjectと呼ばれるもの)を追加してTryGetMemberにキャプチャし、元のオブジェクトを元に戻すこともできます。

16
Jcl
 ExpandoObject eo=JsonConvert. Deserialize<ExpandoObject>(JsonConvert.Serialize(dynamicObject))

ダイナミックをExpandoObjectに変更するために働いた。

1
andrewramka