2011-10-15 60 views
2

我已经定义了一个从基本1继承的class1。我还定义了另一个class2,其中包含类似于class1的simila成员,但是此类继承自base2。按字段复制对象字段

如何将class1转换为class2?

一个选项是我有一个酒店在像

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

时间分配是否有任何.NET更好的选择?

+0

除非他们共享一个共同的接口,你有三个选项,1)一次一行。 2)使用像Automapper这样的工具(易于使用且非常灵活)。 3)使用反射 –

+0

@ Gary.S如果他们确实实现了相同的接口,会发生什么变化?正如我所看到的,你仍然会有相同的3个选项。 –

+0

如果他们实现相同的接口,你可以使用传递接口而不是具体的实现,如果你可以依赖它来定义你需要的属性 –

回答

3

,如果你有很多不同的类型之间做到这一点,你可以考虑使用AutoMapper

2

您当前的解决方案是完全可以接受的,是映射对象A的一个非常明确的方式向对象B

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

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>(); 
+0

不会推荐这种方法。 Automapper将是一个更加强大的解决方案,因为它具有更多的约定,并使用il发射创建自定义解串器,所以它的速度更快。 –

+0

@Yannick Motton,我在代码中看不到任何性能问题,我认为对于OP来说,如何使用反射和一些简单的规则来做他想做的事情是很好的,代码并不难,所以我个人使用此代码,而不是将第三方库添加到我的项目中以解决这样一个简单问题。 –

+0

反射*是瓶颈。虽然我同意减少对第三方库的依赖关系的想法,但重新发明轮子是没有意义的。 –

0

我只是背负的赛义德,但这是一点点更容易使用和阅读:

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>(); 
} 
+0

尽管更具可读性,但实际上并没有这样做。 Saeed的代码将匹配的属性名称对齐。你的代码假设这两种类型在结构上是相同的。考虑如果源类型具有名为'A'的额外属性会发生什么。 –

+0

@YannickMotton哦!你在谈论我的MapNew(),我忘了把打字重新放在那里。在我的版本中,我将它保存在那里,但是我必须将它放回到MapNew()中。感谢您的支持。 – Suamere