c#中合并两个对象
本文关键字:两个 对象 合并 | 更新日期: 2023-09-27 18:19:18
我有一个具有各种属性的对象模型MyObject
。在某一点上,我有这些MyObject
的两个实例:实例A和实例B。如果实例B具有非空值,我想复制和替换实例A中的属性与实例B的属性。
如果我只有一个类3个属性,没有问题,我可以很容易地硬编码它(这是我开始做的)。但是我实际上有12个不同的对象模型,每个模型大约有10个属性。
做这件事的好方法是什么?
更新如果需要经常调用此方法,请使用AutoMapper。Automapper使用Reflection.Emit
构建动态方法,将比反射快得多。
您可以使用反射复制属性的值:
public void CopyValues<T>(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使用相同的方法。
您可以使用反射来做到这一点,但正如有人所说,它将有性能损失。
由于您正在使用预期的类设计,因此可以通过使用如下的扩展方法来实现相同的目标:
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);
在一天结束时,您已经将此操作集中在扩展方法中,如果您添加或删除类的属性,您只需要修改扩展方法的实现,就可以完成所有操作。
我创建了一个类似于上面的一些答案的方法,但它返回两个对象之间合并的新对象,并且只有在第一个对象的值为空时才会合并第二个对象的值。
public T MergeObjects<T>(T primary, T secondary)
{
T obj = (T)Activator.CreateInstance(typeof(T));
Type t = typeof(T);
var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
foreach (var prop in properties)
{
var value = prop.GetValue(primary, null);
if (value != null)
prop.SetValue(obj, value, null);
else
{
value = prop.GetValue(secondary, null);
if (value != null)
prop.SetValue(obj, value, null);
}
}
return obj;
}
你可以使用这个包:XASoft
使用foo.Merger(bar)方法将两个对象组合成一个动态对象
就像这样
var objA = new { a = 1, b = 2, c = 3 };
var newObj = objA.Merger(new { a = "Hey", d = 4, e = 5 });
newObj.e = "There";
newObj.f = 6;
Console.WriteLine(JsonConvert.SerializeObject(newObj));
即使对象列表也可以正常工作!
private class TestClass
{
public int X { get; set; }
public int Y { get; set; }
}
static void Main(string[] args)
{
var list = new List<TestClass> {
new TestClass{ X=1,Y=2},
new TestClass{ X=3,Y=4}
};
Console.WriteLine(JsonConvert.SerializeObject(list.ListMerger(i => new
{ X = "null value", Z = i.X == 1 ? 0 : 1 })));
}
哦,看起来像javascript语言…
顺便说一句,源代码点击这里
我已经为此编写了自己的类:ObjectMerger.
基本上它使用反射(因此可能很慢)。它还包含了更多的特性,例如解析循环引用的对象并合并它们。我的ObjectMerger还包含处理更复杂的类(如Delegate
或MemberInfo
)的机制。这些对象将被完全复制,类中的其他对象将被递归合并。
语法类似于:
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<T>(IList<T> targetList, IList<T> sourceList, Func<T, int> selector)
{
var matchingPrimaryKey = targetList.Select(x => selector(x)).ToList();
foreach (var thismatchingPrimaryKey in matchingPrimaryKey)
{
CopyValues<T>(targetList.Single(x => selector(x) == thismatchingPrimaryKey),
sourceList.Single(x => selector(x) == thismatchingPrimaryKey));
}
}
private static void CopyValues<T>(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);
}
}
}