按字段复制对象

时间:2011-10-15 10:23:05

标签: c# .net optimization

我已经定义了一个继承自base 1的class1。我还定义了另一个class2,它包含了class1中的simila成员,但是这个类继承自base2。

如何将class1转换为Class2?

一个选项是我必须一次分配一个属性,如

Class2.a = Class1.a;
Class2.b = Class1.b;
Class2.c = Class1.c;

.NET中有更好的选择吗?

4 个答案:

答案 0 :(得分:4)

您可以编写自己的扩展方法,如下图:

public static class ExtendedClassPropMapping
{
    public static Y MapTo<T, Y>(this T input) where Y : class, new()
    {
        Y output = new Y();
        var propsT = typeof(T).GetProperties();
        var propsY = typeof(Y).GetProperties();

        var similarsT = propsT.Where(x => 
                      propsY.Any(y => y.Name == x.Name 
               && y.PropertyType == x.PropertyType)).OrderBy(x=>x.Name).ToList();

       var similarsY = propsY.Where(x=>
                       propsT.Any(y=>y.Name == x.Name 
               && y.PropertyType == x.PropertyType)).OrderBy(x=>x.Name).ToList();

        for (int i=0;i<similarsY.Count;i++)
        {
            similarsY[i]
            .SetValue(output, similarsT[i].GetValue(input, null), null);
        }

        return output;
    }
}

并使用它:

var test = firstObject.MapTo<class1, class2>();

答案 1 :(得分:3)

如果必须在许多不同类型之间进行,可以考虑使用AutoMapper

答案 2 :(得分:2)

您当前的解决方案是完全可以接受的,并且是将对象A映射到对象B的非常明确的方法。

大多数映射库(如AutoMapper)允许基于约定的映射。如果属性名称和类型对齐,它将为您映射,几乎不需要任何配置。根据目标对象的相似程度,这种方法可能仍需要您做一些工作。缺点是它不是那么明确,取决于你需要做的手动配置的数量,你可能只是增加了复杂性。

答案 3 :(得分:0)

我只是从Saeed那里扛起来,但这更容易使用和阅读:

public static class ExtendedClassPropMapping
{
    public static Y MapTo<Y>(this object input) where Y : class, new()
    {
        Y output = new Y();
        var propsT = input.GetType().GetProperties();
        var propsY = typeof(Y).GetProperties();

        var similarsT = propsT.Where(x =>
                      propsY.Any(y => y.Name == x.Name
               && y.PropertyType == x.PropertyType)).OrderBy(x => x.Name).ToList();

        var similarsY = propsY.Where(x =>
                        propsT.Any(y => y.Name == x.Name
                && y.PropertyType == x.PropertyType)).OrderBy(x => x.Name).ToList();

        for (int i = 0; i < similarsY.Count; i++)
        {
            similarsY[i]
            .SetValue(output, similarsT[i].GetValue(input, null), null);
        }

        return output;
    }

    public static T MapNew<T>(this T input) where T : class, new()
    {
        T output = new T();

        var similarsT = input.GetType().GetProperties().OrderBy(x => x.Name).ToList();
        var similarsY = output.GetType().GetProperties().OrderBy(x => x.Name).ToList();

        for (int i = 0; i < similarsY.Count; i++)
        {
            similarsY[i]
            .SetValue(output, similarsT[i].GetValue(input, null), null);
        }

        return output;
    }
}

然后你可以像这样使用它们:

public Teacher ConvertInterfaceToClass(ITeacher teacher)
{
    return teacher.MapTo<Teacher>();
}

public void CopyTeacher(Teacher source, out Teacher destination)
{
    destination = source.MapTo<Teacher>();
}