可以在一个动态对象转换为ExpandoObject(C#)

可以在一个动态对象转换为ExpandoObject(C#)

问题描述:

我收到从驱动程序API(在DLL)密封类类型的动态对象。我想装饰与一些附加属性这个对象

I am getting an dynamic object of type "Sealed Class" from a driver api (in dll). I want to decorate this object with a few additional properties.

我想做些事情的效果:

public void expandIT(dynamic sealedObject) {

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






更新

我喜欢JCL的解决方案。但我想做的事,这是更容易地创建一个ExpandoObject,然后嵌入动态密封类对象作为子项属性,然后加我的属性到父ExpandoObject。谢谢JCL,我是在脑冻结至于如何做到这一点。

I like JCL's solution. But for what I wanted to do, it was easier to create a ExpandoObject and then embed the Dynamic sealed class object as a child property, and then add my properties to the parent ExpandoObject. Thanks JCL, I was in brain-freeze as to how to do this. I

不。 A 动态对象并不强制在编译时的类型,但它不会神奇地让你的对象扩展(除非它是一个 ExpandoObject )。

Nope. A dynamic object doesn't enforce the type at compile time, but it doesn't magically make your object expandable (unless it's an ExpandoObject).

您可以但是,让使用某种包装或代理的 DynamicObject ...是这样的:

You can however, make some kind of wrapper or proxy using DynamicObject... something like:

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().GetProperties().FirstOrDefault
        (propertyInfo => propertyInfo.Name == 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(GetMemberBinder 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;          
    }      
}



然后你就可以使用它像:

And then you can use it like:

dynamic myExpandedObject = new ExpandedObjectFromApi(sealedObject);

这应该返回原来的对象属性如果找到,如果没有该名称的属性是在原对象时,它会添加为自定义属性。

This should return the original object properties if found, or if no property of that name is in the original object, it'll add it as a "custom" property.

我所做的代码的堆栈溢出编辑器,可能犯了很多错误的,它不是适合复制/粘贴,它需要吨错误检查(也需要实现字段和方法中,如果所接收的对象有它们)。刚写的,所以你得到的基本思想。

I've made the code in the Stack Overflow editor and probably made a lot of mistakes, it's not suitable for copy/paste, and it needs tons of error checking (also needs to implement fields and methods, if the received object has them). Just wrote it so you get the basic idea.

您可能还需要增加一个特殊的属性(一种叫做 WrappedObject ,例如)和捕捉它在 TryGetMember ,这样你就可以得到原来的对象了。

You also may want to add a special property (something called WrappedObject, for example) and capture it in TryGetMember, so you can get the original object back.