.NET/C#中是否内置了用于在对象之间复制值的内容

本文关键字:复制 之间 对象 用于 是否 内置 NET | 更新日期: 2023-09-27 18:21:22

假设您有两个类似的类:

public class ClassA {
    public int X { get; set; }
    public int Y { get; set; }
    public int Other { get; set; }
}
public class ClassB {
    public int X { get; set; }
    public int Y { get; set; }
    public int Nope { get; set; }
}

现在假设你有每个类的一个实例,你想把值从a复制到b。有没有像MemberwiseClone这样的东西可以复制属性名称匹配的值(当然是容错的——一个有get,另一个有set,等等)?

var a = new ClassA(); var b = new classB();
a.CopyTo(b); // ??

在JavaScript这样的语言中,这样的操作非常简单。

我猜答案是否定的,但也许还有一个简单的选择。我已经编写了一个反射库来实现这一点,但如果在较低级别上内置到C#/.NET中,可能会更高效(以及为什么要重新发明轮子)。

.NET/C#中是否内置了用于在对象之间复制值的内容

框架中没有任何对象对象映射,但有一个非常流行的库可以做到这一点:AutoMapper。

AutoMapper是一个简单的小库,用于解决复杂问题-去掉将一个对象映射到的代码另一个这种类型的代码写起来相当枯燥乏味,所以为什么不发明一种工具来为我们做这件事呢?

顺便说一句,只是为了学习,这里有一个简单的方法,你可以实现你想要的。我还没有对它进行彻底的测试,它的健壮性/灵活性/性能也不如AutoMapper,但希望能从总体想法中得到一些东西:

public void CopyTo(this object source, object target)
{
    // Argument-checking here...
    // Collect compatible properties and source values
    var tuples = from sourceProperty in source.GetType().GetProperties()
                 join targetProperty in target.GetType().GetProperties() 
                                     on sourceProperty.Name 
                                     equals targetProperty.Name
                 // Exclude indexers
                 where !sourceProperty.GetIndexParameters().Any()
                    && !targetProperty.GetIndexParameters().Any()
                 // Must be able to read from source and write to target.
                 where sourceProperty.CanRead && targetProperty.CanWrite
                 // Property types must be compatible.
                 where targetProperty.PropertyType
                                     .IsAssignableFrom(sourceProperty.PropertyType)
                 select new
                 {
                     Value = sourceProperty.GetValue(source, null),
                     Property = targetProperty
                 };
    // Copy values over to target.
    foreach (var valuePropertyTuple in tuples)
    {
        valuePropertyTuple.Property
                          .SetValue(target, valuePropertyTuple.Value, null);
    }
}

据我所知,.NET中没有类似的东西,但有一个库能够做到这一点(以及更多),那就是AutoMapper。对于您的案例,类似于:

_mapper.Map<A, B> (a, b);

据我所知,这并不存在。我做这件事的方式是:

public static T DeepCopy(T oldclass)
{
    using (MemoryStream stream = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, oldclass);
        ms.Position = 0;
        return (T)formatter.Deserialize(stream);
    }
}

请参阅接口System.ICloneable和方法System.Object.MemberwiseClone()。如MSDN文档中所述,

MemberwiseClone方法通过创建一个新对象,然后将当前对象的非静态字段复制到新对象,来创建一个浅拷贝。如果字段是值类型,则执行该字段的逐位复制。如果字段是引用类型,则复制引用,但不复制引用的对象;因此,原始对象及其克隆引用的是同一个对象