使用反射c#将动态对象转换为类型

Tim*_*ens 10 c# reflection

请考虑以下代码

 var currentType = Type.GetType("Some.Type, Some");
 dynamic myDynamic = new System.Dynamic.ExpandoObject();
 myDynamic.A = "A";
 var objectInCorrectType = ???
Run Code Online (Sandbox Code Playgroud)

如何将动态转换为currentType?

Ere*_*mez 11

您无法将动态对象强制转换为特定类型,如@Lasse所述.

但是,你的问题提到"反思",所以我怀疑你正在寻找一种方法来简单地映射属性值(即在Lasse的评论中"创建一个新的X并复制值等"):

...
myDynamic.A = "A";

// get settable public properties of the type
var props = currentType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
    .Where(x => x.GetSetMethod() != null);

// create an instance of the type
var obj = Activator.CreateInstance(currentType);

// set property values using reflection
var values = (IDictionary<string,object>)myDynamic;
foreach(var prop in props)
    prop.SetValue(obj, values[prop.Name]);
Run Code Online (Sandbox Code Playgroud)


Mat*_*zer 9

dynamic鸭子类型的变量(即延迟类型检查到运行时)。它仍然拥有一个类型化的对象,但在编译时不会被检查。

因此,由于 anExpandoObject是一种类型,如果您将它分配给类型化或动态引用,则不能ExpandoObject仅仅因为它与目标类型共享相同的成员就将其强制转换或转换为类型。

顺便说一句,由于ExpandoObjectimplements IDictionary<string, object>,您可以实现某种从ExpandoObject实例到目标类型的动态映射,其中成员作为扩展方法匹配:

public static class ExpandObjectExtensions
{
    public static TObject ToObject<TObject>(this IDictionary<string, object> someSource, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
           where TObject : class, new ()
    {
        Contract.Requires(someSource != null);
        TObject targetObject = new TObject();
        Type targetObjectType = typeof (TObject);

        // Go through all bound target object type properties...
        foreach (PropertyInfo property in 
                    targetObjectType.GetProperties(bindingFlags))
        {
            // ...and check that both the target type property name and its type matches
            // its counterpart in the ExpandoObject
            if (someSource.ContainsKey(property.Name) 
                && property.PropertyType == someSource[property.Name].GetType())
            {
                property.SetValue(targetObject, someSource[property.Name]);
            }
        }

        return targetObject;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,尝试以下代码,它会按您的预期工作:

public class A 
{
    public int Val1 { get; set; }
}

// Somewhere in your app...
dynamic expando = new ExpandoObject();
expando.Val1 = 11;

// Now you got a new instance of A where its Val1 has been set to 11!
A instanceOfA = ((ExpandoObject)expando).ToObject<A>();
Run Code Online (Sandbox Code Playgroud)

实际上,我已经基于其他问答来回答这个问题,在那里我可以解决将对象映射到字典和反之亦然的类似问题: 将对象映射到字典,反之亦然