.NET/C#中是否有内置的功能可以在对象之间复制值?

10

假设您有以下两个类:

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 的更低层级内置该功能可能会更有效率(何必重复造轮子呢)。


2
请查看AutoMapper: http://lostechies.com/jimmybogard/2009/01/23/automapper-the-object-object-mapper/ - Davide Piras
4个回答

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

在我所知道的.NET中没有类似的东西,但是一个能够做到这一点(以及更多)的库是AutoMapper。对于你的情况,可以使用以下代码:

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

-1
请查看接口System.ICloneable和方法System.Object.MemberwiseClone()。如MSDN文档所述, MemberwiseClone方法通过创建一个新对象并将当前对象的非静态字段复制到新对象来创建浅表副本。如果字段是值类型,则执行字段的逐位复制。如果字段是引用类型,则复制引用但不复制所引用的对象;因此,原始对象及其克隆引用同一对象。

你是说这个会起作用吗?classB = classA.MemberwiseClone() as classB - L.B

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

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