从基础 类 构建 Expando 对象(以便使用基础构造函数、方法和属性)并向其添加其他属性和方法

Building Expando Objects out of base classes (so that base Constructor, methods and properties are used) and add other properties and methods to it

有没有办法从非 expandoObject 基础构建 Expando 对象 class?
换句话说,我正在尝试做这样的事情:

// Instantiate my Expando object
dynamic myDynamicObject = new ExpandoObject();
// Add some base class to it - SomeBaseClass() can contain anything (Properties and methods)
myDynamicObject =  Add SomeBaseClass(); ???
// Add some other properties that are not in the base class
myDynamicObject.Name = "My Dynamic Object";
// Add some methods
myDynamicObject.SomeMethods = (Func<bool>)(() => {
   return true;
});

编辑

正如 Martheen 所建议的,我们可以根据这个 Whosebug 从另一个对象构造一个 Expando。这是他们的工作:

public static dynamic ToDynamic<T>(this T obj)
{
   IDictionary<string, object> expando = new ExpandoObject();

   foreach (var propertyInfo in typeof(T).GetProperties())
   {
       var currentValue = propertyInfo.GetValue(obj);
       expando.Add(propertyInfo.Name, currentValue);
   }
   return expando as ExpandoObject;
}

然而,这个例子只处理属性,但我还需要方法。

所以我尝试为这些方法做一些类似的事情,但我真的不知道我在做什么:

public static dynamic ToDynamic<T>(this T obj)
{
   IDictionary<string, object> expando = new ExpandoObject();

   MethodInfo[] info = typeof(T).GetMethods();

   foreach (var methodInfo in info)
   {
      if (methodInfo != null)
      {
          var currentMethod = methodInfo.GetMethodBody();
          expando.Add(methodInfo.Name, currentMethod);
      }
   }
   return expando as ExpandoObject;
}

但是当尝试执行方法时我得到这个错误:

An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Unknown Module.

附加信息:无法调用非委托类型

基于 this answer,稍作替换以不依赖额外的 class

public class Expando : DynamicObject
{
    public object Instance;
    Dictionary<string, dynamic> ExtraProperties = new Dictionary<string, dynamic>();

    public Expando(object instance)
    {
        Instance = instance;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        try
        {
            result = Instance.GetType().GetProperty(binder.Name).GetValue(Instance,null);
            return true;
        }
        catch
        {
            if (ExtraProperties.Keys.Contains(binder.Name))
            {
                result = ExtraProperties[binder.Name];
                return true;
            }
        }

        result = null;
        return false;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        try
        {
            Instance.GetType().GetProperty(binder.Name).SetValue(Instance, value,null);
        }
        catch (Exception ex)
        {
            ExtraProperties[binder.Name] = value;
        }

        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        try
        {
            result = Instance.GetType().GetMethod(binder.Name,args.Select(a=>a.GetType()).ToArray()).Invoke(Instance, args);
            return true;
        }
        catch
        { }

        result = null;
        return false;
    }

    public override string ToString()
    {
        return Instance.ToString();
    }

}

如果它在您使用的 classes 上崩溃并烧毁,请尝试原始答案(如果其他 class link 尚未更新,请使用 https://github.com/RickStrahl/Westwind.Utilities/blob/master/Westwind.Utilities/Utilities/ReflectionUtils.cs

请注意,成员的 return 类型没有改变。这意味着,例如,如果您在字符串上使用 Expando,您的 Expando 会响应 Replace 和 PadLeft,但 returned 结果是一个字符串,而不是您的 Expando,这可能是您想要的,也可能不是您想要的。如果您仍然需要它,则必须将它重新装回您的 Expando 中。此外,此解决方案对可能适用于原始 class 的扩展方法视而不见。