如何将c#动态变量属性分配给另一个动态对象

本文关键字:动态 分配 另一个 对象 属性 变量 | 更新日期: 2023-09-27 18:19:13

我试图写一个函数,创建类型t的对象并分配其属性。

    internal static object CreateInstanceWithParam(Type t, dynamic d)
    {
        //dynamic obj =  t.GetConstructor(new Type[] { d }).Invoke(new object[] { d });
        dynamic obj =  t.GetConstructor(new Type[] { }).Invoke(new object[] { });
        foreach (var prop in d.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
        {
            //prop.Name, 
            //prop.GetValue(d, null);
            // assign the properties and corresponding values to newly created object ???
        }
        return obj;
    }

那么我应该可以将它用于任何类型的类,比如

IUser user = (IUser)CreateInstanceWithParam(userType, new { UserID = 0, Name = "user abc", LoginCode = "abc", DefaultPassword = "xxxxxx" });
IUnit newUnit = (IUnit)CreateInstanceWithParam(unitType, new { ID = 3, Code = "In", Name = "Inch", Points = "72" })

如何将属性prop.Name分配给obj

如何将c#动态变量属性分配给另一个动态对象

假设您只是试图复制属性,您根本不需要dynamic:

internal static object CreateInstanceWithParam(Type type, object source)
{
    object instance = Activator.CreateInstance(type);
    foreach (var sourceProperty in d.GetType()
                                    .GetProperties(BindingFlags.Instance | 
                                                   BindingFlags.Public))
    {
        var targetProperty = type.GetProperty(sourceProperty.Name);
        // TODO: Check that the property is writable, non-static etc
        if (targetProperty != null)
        {
            object value = sourceProperty.GetValue(source);
            targetProperty.SetValue(instance, value);
        }
    }
    return instance;
}

实际上,在这里使用dynamic可能是一个不好的事情;传入的对象是匿名类型的实例——不需要dynamic。特别是,dynamic成员访问与反射不同,并且您不能保证描述为dynamic的对象将从.GetType().GetProperties()返回任何感兴趣的;考虑ExpandoObject

但是,FastMember(在NuGet上可用)可能很有用:

internal static object CreateInstanceWithParam(Type type, object template)
{
    TypeAccessor target = TypeAccessor.Create(type),
        source = TypeAccessor.Create(template.GetType());
    if (!target.CreateNewSupported)
            throw new InvalidOperationException("Cannot create new instance");
    if (!source.GetMembersSupported)
            throw new InvalidOperationException("Cannot enumerate members");
    object obj = target.CreateNew();
    foreach (var member in source.GetMembers())
    {
        target[obj, member.Name] = source[template, member.Name];
    }
    return obj;
}

特别地,这可以像使用反射API一样轻松地使用dynamic API,并且您永远不会通常看到差异。