在C#中合并两个对象

我有一个具有各种属性的对象模型MyObject。 有一次,我有两个这样的MyObject实例:实例A和实例B.如果实例B具有非空值,我想将实例A中的属性复制并替换为实例B的属性。

如果我只有1个具有3个属性的类,没问题,我可以轻松地对其进行硬编码(这是我开始做的)。 但实际上我有12个不同的对象模型,每个模型有10个属性。

有什么好办法呢?

更新如果需要大量调用此方法,请改用AutoMapper 。 Automapper使用Reflection.Emit构建动态方法,并且比reflection快得多。

您可以使用reflection复制属性的值:

 public void CopyValues(T target, T source) { Type t = typeof(T); var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite); foreach (var prop in properties) { var value = prop.GetValue(source, null); if (value != null) prop.SetValue(target, value, null); } } 

我已经通用它来确保类型安全。 如果要包含私有属性,则应使用Type.GetProperties()的重写,指定绑定标志。

我已经尝试过Kyle Finley将两个对象合并为一个匿名类型 ,它的工作非常完美。

使用TypeMerger ,合并就像一样简单

 var obj1 = new {foo = "foo"}; var obj2 = new {bar = "bar"}; var mergedObject = TypeMerger.MergeTypes(obj1 , obj2 ); 

这就是你得到了合并的对象,除此之外,还有一个规定可以忽略特定的属性。 你也可以对MVC3使用相同的东西。

你可以使用reflection来做到这一点,但正如有人所说,它会有性能损失。

由于您正在使用预期的类设计,因此可以通过使用类似的扩展方法来实现相同的目标:

 public static class MyClassExtensions { public static void Merge(this MyClass instanceA, MyClass instanceB) { if(instanceA != null && instanceB != null) { if(instanceB.Prop1 != null) { instanceA.Prop1 = instanceB.Prop1; } if(instanceB.PropN != null) { instanceA.PropN = instanceB.PropN; } } } 

后来,代码中的某个地方:

 someInstanceOfMyClass.Merge(someOtherInstanceOfMyClass); 

在一天结束时,您已将此操作集中在扩展方法中,如果添加或删除类的属性,则只需修改扩展方法的实现,即可完成所有操作。

我为此目的编写了自己的类: ObjectMerger 。

基本上它使用reflection(因此可能很慢)。 它还包含更多function,例如解析循环引用的对象并合并它们。 我的ObjectMerger还包含处理更复杂的类(如DelegateMemberInfo 。 这些将被完全复制,类中的其他对象以递归方式合并。

语法如下:

 var initialInstance = new MyObjectBase(); // Initialize first object var properInstance = new MyObjectWithAlgorithms(); // Initialize second object var result = ObjectMerger.MergeObjects(properInstance, initialInstance); // Merge Objects into type of "properInstance" 

我很遗憾地说它不能按原样使用,因为由于我公司的限制,目前存储库中缺少一些外部库,但它们很容易被重写。 我希望将来可以添加它们。

这与@Bas答案相同,但对于合并2个对象列表

 public class Copycontents { public static void Work(IList targetList, IList sourceList, Func selector) { var matchingPrimaryKey = targetList.Select(x => selector(x)).ToList(); foreach (var thismatchingPrimaryKey in matchingPrimaryKey) { CopyValues(targetList.Single(x => selector(x) == thismatchingPrimaryKey), sourceList.Single(x => selector(x) == thismatchingPrimaryKey)); } } private static void CopyValues(T target, T source) { Type t = typeof(T); var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite); foreach (var prop in properties) { var value = prop.GetValue(source, null); if (value != null) prop.SetValue(target, value, null); } } }