同名变量 - 两个不同的类 - 如何将值从一个类复制到另一个类 - 反射 - C#

6

不使用AutoMapper...(因为负责此项目的某人会看到依赖项而感到惊恐)

我有一个类(A类)具有任意数量的属性。我有另一个类(B类),具有相同的属性(相同的名称和类型)。Class B也可以有其他不相关的变量。

是否有一些简单的反射代码可以将值从A类复制到B类?

越简单越好。


Automaper!! 这段代码已经为您编写好了。 - Maxim
你还可以使用Fasterflect(http://fasterflect.codeplex.com)来实现对象映射和克隆,它是基于动态IL生成的服务(但这样也会有依赖性)。 - Morten Mertner
5个回答

23
Type typeB = b.GetType();
foreach (PropertyInfo property in a.GetType().GetProperties())
{
    if (!property.CanRead || (property.GetIndexParameters().Length > 0))
        continue;

    PropertyInfo other = typeB.GetProperty(property.Name);
    if ((other != null) && (other.CanWrite))
        other.SetValue(b, property.GetValue(a, null), null);
}

多余的括号是怎么回事?另外请注意,复制任何引用类型属性仍将指向原始对象。 - Morten Mertner
@morten 我并没有复制属性本身。我是使用 SetValue 和 GetValue 来 设置 值的。所以我认为这应该没问题吧?我说得对吗? - Issa Fram
@Issa 这取决于你想要的行为 :) 你正在设置属性值,但如果该值是一个对象引用,那么你所做的对应于 "var a = new object(); var b = a;"。也就是说,你只是复制了引用,而没有创建被引用对象的深层克隆。 - Morten Mertner
@Morten,这些变量只是双精度类型,所以我认为没问题。但是,是的,我理解你的意思。感谢你提醒。 - Issa Fram

4

这个?

static void Copy(object a, object b)
{
    foreach (PropertyInfo propA in a.GetType().GetProperties())
    {
        PropertyInfo propB = b.GetType().GetProperty(propA.Name);
        propB.SetValue(b, propA.GetValue(a, null), null);
    }
}

该死,你比我快。然而,你需要为所有成员而不仅仅是属性做到这一点。 - Jonathan Henson

1
如果您将它用于多个对象,那么获取映射器可能很有用:
public static Action<TIn, TOut> GetMapper<TIn, TOut>()
{
    var aProperties = typeof(TIn).GetProperties();
    var bType = typeof (TOut);

    var result = from aProperty in aProperties
                 let bProperty = bType.GetProperty(aProperty.Name)
                 where bProperty != null &&
                       aProperty.CanRead &&
                       bProperty.CanWrite
                 select new { 
                              aGetter = aProperty.GetGetMethod(),
                              bSetter = bProperty.GetSetMethod()
                            };

    return (a, b) =>
               {
                   foreach (var properties in result)
                   {
                       var propertyValue = properties.aGetter.Invoke(a, null);
                       properties.bSetter.Invoke(b, new[] { propertyValue });
                   }
               };
}

1

我知道你要求反射代码,这是一个旧帖子,但我有一个不同的建议想要分享。它可能比反射更快。

您可以将输入对象序列化为JSON字符串,然后反序列化为输出对象。所有具有相同名称的属性都将自动分配给新对象的属性。

var json = JsonConvert.SerializeObject(a);
var b = JsonConvert.DeserializeObject<T>(json);

0

试试这个:

PropertyInfo[] aProps = typeof(A).GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);

PropertyInfo[] bProps = typeof(B).GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);

    foreach (PropertyInfo pi in aProps)
                {
                    PropertyInfo infoObj = bProps.Where(info => info.Name == pi.Name).First();
                    if (infoObj != null)
                    {
                        infoObj.SetValue(second, pi.GetValue(first, null), null);
                    }
                }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接