我希望找到一种方法来获取具有相同属性的两个对象,并调用将属性值从一个对象复制到另一个对象。下面的示例假设我有一个A的实例,我想使用该实例的数据来水合新的实例或C(为了保持简洁,我使用了字段而不是下面示例中的属性)
public class A : B
{
public string prop1;
public int prop2;
}
public class B
{
public byte propX;
public float propY;
}
public class C
{
public byte propX;
public float propY;
public string prop1;
public int prop2;
}
public class Merger
{
public static object Merge(object copyFrom, object copyTo)
{
//do some work
//maybe <T> generically refactor?
}
}
合并类只是一个假的例子,通过泛型来做这个是最优的,但我首先要问的是这样的能力是否已经存在。我可以想象自己使用反射来做这件事,但我只是想先把它扔出来以获得更好的想法。
真实世界上下文:这实际上是一个与MVVM相关的问题,因为我试图使用从EF回来的不同类来填充ViewModel实例。
答案 0 :(得分:8)
查看AutoMapper之类的工具和库 - 这些工具和库可以轻松处理这样的案例 - 还有更多!无需重新发明轮子 - 只需使用该工具! : - )
您基本上会在A和C类之间定义一个映射,如下所示:
Mapper.CreateMap<A, C>();
然后,您可以让AutoMapper根据该映射从A的实例到C的实例进行映射,如下所示:
C yourC = Mapper.Map<A, C>(instanceOfA);
AutoMapper根据属性名称(和类型)执行默认映射,但您可以通过多种方式扩展和影响它,以包括从一个属性到另一个属性的映射,即使名称(或类型)不匹配100%。这是非常灵活和完善的 - 绝对值得认真看待!
答案 1 :(得分:1)
using System;
using System.Linq;
using System.Reflection;
public class Merger
{
public static TTarget Merge<TTarget>(object copyFrom) where TTarget : new()
{
var flags = BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic;
var targetDic = typeof(TTarget).GetFields(flags)
.ToDictionary(f => f.Name);
var ret = new TTarget();
foreach (var f in copyFrom.GetType().GetFields(flags))
{
if (targetDic.ContainsKey(f.Name))
targetDic[f.Name].SetValue(ret, f.GetValue(copyFrom));
else
throw new InvalidOperationException(string.Format(
"The field “{0}” has no corresponding field in the type “{1}”.",
f.Name, typeof(TTarget).FullName));
}
return ret;
}
}
class Program
{
static void Main(string[] args)
{
var a = new A { prop1 = "one", prop2 = 2, propX = 127, propY = 0.47f };
var c = Merger.Merge<C>(a);
Console.WriteLine(c.prop1); // prints one
Console.WriteLine(c.prop2); // prints 2
Console.WriteLine(c.propX); // prints 127
Console.WriteLine(c.propY); // prints 0.47
}
}
答案 2 :(得分:0)
到目前为止,这不是最好的解决方案,但基于您提供的对象图,您可以通过XML序列化第一个对象,并将XML反序列化为第二个对象来实现此目的。
您提议的Merger
方法可能如下所示:
public class Merger
{
public static object Merge(object copyFrom, object copyTo)
{
var xmlContent = MyXMLSerializationMethod(copyFrom);
MyXMLDeserializationMethod(xmlContent, typeof(copyTo), out copyTo);
return copyTo;
}
}
答案 3 :(得分:0)
关于使用AutoMapper在MVVM和MVC上下文中解决此问题的好帖子
http://www.bengtbe.com/blog/post/2009/04/14/Using-AutoMapper-to-map-view-models-in-ASPNET-MVC.aspx