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

时间:2012-01-23 18:07:59

标签: c# .net copy

假设您有两个类,如下所示:

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可能会更有效(以及为什么重新发明轮子)。

4 个答案:

答案 0 :(得分:10)

框架中没有任何对象 - 对象映射,但有一个非常受欢迎的库可以做到这一点: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);

    }
}

答案 1 :(得分:1)

在我所知道的.NET中没有这样的东西,但是能够做到这一点(以及更多)的一个库是AutoMapper。对于您的情况,例如:

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

答案 2 :(得分:-1)

据我所知,这不存在。我一直在做的方式是:

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);
    }
}

答案 3 :(得分:-1)

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

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