我有一个具有各种属性的对象模型MyObject。有一点,我有这些MyObject的两个实例:实例A和实例B.我想复制和替换实例A中的属性与实例B的属性,如果实例B具有非空值。在C中合并两个对象#
如果我只有1个类有3个属性,没问题,我可以很容易地对它进行硬编码(这是我开始做的)。但我实际上有12个不同的对象模型,每个模型都有10个属性。
这样做的好方法是什么?
我有一个具有各种属性的对象模型MyObject。有一点,我有这些MyObject的两个实例:实例A和实例B.我想复制和替换实例A中的属性与实例B的属性,如果实例B具有非空值。在C中合并两个对象#
如果我只有1个类有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(),指定绑定标志。
您可以使用反射来做到这一点,但正如有人所说,它会有性能损失。
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);
既然你与预期一流的设计工作,您可以通过使用扩展方法,像这样达到同样的目的
在一天结束时,您已经将此操作集中在一个扩展方法中,并且如果您添加或删除了类的某个属性,则只需修改扩展方法的实现,即可完成所有操作。
这仍然会导致可维护性问题,因为OP提到 – Bas 2012-01-02 15:49:50
@BasB我不确定这一点,因为正如我在答复中所写的那样,这是一个可预测的设计,我怀疑这个班会加班或删除大量属性。所以,如我所说,在一天结束时,它具有与反思一样的效果,而不会影响性能。 – 2012-01-02 15:52:37
@BasB另外,这些可维护性问题可以在Visual Studio中使用T4模板来解决,因此删除或添加属性可以触发代码生成过程并重新创建此扩展方法。为什么不? WCF和许多.NET框架正在使用代码生成来解决此问题:) – 2012-01-02 15:54:30
我试过Merge Two Objects into an Anonymous Type由凯尔芬利,它是完美的工作。
随着TypeMerger
合并很简单,只要
var obj1 = new {foo = "foo"};
var obj2 = new {bar = "bar"};
var mergedObject = TypeMerger.MergeTypes(obj1 , obj2);
就是这样,你得到的合并对象,除此之外,还有一项规定过于忽略特定属性。您也可以为MVC3使用相同的功能。
好的,谢谢你的回答 – frenchie 2012-04-21 17:45:19
注意:链接不再可用。 – stephenbayer 2014-03-19 22:04:50
@stephenbayer链接现在备份.. – 2014-06-27 13:14:55
这是一样的@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);
}
}
}
我写我自己的类用于此目的: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"
我很抱歉地说,这不是原样使用,因为一些外部库在此刻的仓库丢失是由于我公司的限制,但他们可以很容易地被重写。我希望将来可以添加它们。
你有没有尝试过像AutoMapper(http://automapper.codeplex.com/)? – 2012-01-02 15:37:36
明显的选择是反思,但你会支付表现的惩罚... – jondavidjohn 2012-01-02 15:37:58
看看这个答案;我认为它涵盖了你的情况: http://stackoverflow.com/questions/571982/iterating-over-class-properties – StilesCrisis 2012-01-02 15:38:27