【发布时间】:2015-08-13 03:07:09
【问题描述】:
我有一个复杂的对象,它有很多属性,包括字符串、小数和 ObservableColection、列表...
我想这样做:
foreach (ITransactionItem transactionItem in Transaction.TransactionItemCollection.ToList())
{
transactionItem.PickUpQuantity = 0;
transactionItem.IsPickUp = false;
this.PickUpItemCollection.Add(transactionItem);
}
问题是,当我更改 PickUpItemCollection 中的项目时,TransactionItemCollection 中的参考项目也更改了,我不想要它。
我尝试使用此 ExtensionMethod 从对象复制对象:
public static T CopyFrom<T>(this T toObject, object fromObject)
{
var fromObjectType = fromObject.GetType();
foreach (PropertyInfo toProperty in toObject.GetType().GetProperties())
{
PropertyInfo fromProperty = fromObjectType.GetProperty(toProperty.Name);
if (fromProperty != null) // match found
{
// check types
var fromType = Nullable.GetUnderlyingType(fromProperty.PropertyType) ?? fromProperty.PropertyType;
var toType = Nullable.GetUnderlyingType(toProperty.PropertyType) ?? toProperty.PropertyType;
if (toType.IsAssignableFrom(fromType)&& toProperty.CanWrite)
{
toProperty.SetValue(toObject, fromProperty.GetValue(fromObject, null), null);
}
}
}
return toObject;
}
并在此代码块中实现为:
foreach (ITransactionItem transactionItem in Transaction.TransactionItemCollection.AsEnumerable().ToList())
{
ITransactionItem transactionItemModel = new TransactionItemModel();
transactionItemModel.CopyFrom(transactionItem);
transactionItem.PickUpQuantity = 0;
transactionItem.IsPickUp = false;
this.PickUpItemCollection.Add(transactionItemModel);
}
但问题仍然存在,我知道我可以将 transactionItemModel 的属性一一设置为 transactionItem 的属性,但是有很多属性,它也有很多 List/ObservableCollection。我认为这会是一个更好的主意,对吧?
请帮帮我。
谢谢
【问题讨论】:
-
CopyFrom将返回一个新对象,它不会修改现有对象。 -
CopyFrom不是递归的;如果PickUpItemCollection上的属性之一是一个对象,并且您在CopyFrom创建的实例上更改了该对象,则原始属性值也会更改,因为PickUpItemCollection的两个实例将引用同一个对象。 -
您可能需要编写一个新函数来代替将整数、字符串等设置为相同的值,并创建具有复制值的任何类对象的新实例
-
考虑使用
BinaryFormatter或Json.NET 进行克隆,就像对这个问题Deep cloning objects 的第一个答案一样。 -
更多选项,请看这里:Faster deep cloning。