Reputation: 360
I have a complex object with a lot of Properties with string, decimal and ObservableColection, List...
I want to do this:
foreach (ITransactionItem transactionItem in Transaction.TransactionItemCollection.ToList())
{
transactionItem.PickUpQuantity = 0;
transactionItem.IsPickUp = false;
this.PickUpItemCollection.Add(transactionItem);
}
The problem is, when I change item in PickUpItemCollection, reference item in TransactionItemCollection is changed too and I don't want it.
I tried to use this ExtensionMethod to Copy object from object:
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;
}
and implement into this code block as:
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);
}
But problem is still there, I know I can set property of transactionItemModel as property of transactionItem one by one but there are a lot of properties and it has a lot of List/ObservableCollection too. I think it would be have a better idea for this, right?
Please help me.
Thanks
Upvotes: 0
Views: 8989
Reputation: 116876
Since your source and target are not necessarily of the same type (ITransactionItem
and TransactionItemModel
respectively) and your target object is pre-allocated, you could (recursively) deep-copy all public properties and fields from the source to the target by serializing to JSON, then populating them in the target with the PopulateObject
method of Json.NET:
public static class ObjectExtensions
{
public static void CopyFrom<TTo, TFrom>(this TTo target, TFrom source) where TTo : class
{
if (target == null)
throw new ArgumentNullException();
// Preserve object graph structure and handle polymorphic fields.
var settings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All, ReferenceLoopHandling = ReferenceLoopHandling.Serialize, TypeNameHandling = TypeNameHandling.Auto };
var json = JsonConvert.SerializeObject(source, settings);
JsonConvert.PopulateObject(json, target, settings);
}
}
Most other serializers don't support populating an existing object which is why I suggest this particular method. Deep-copying with BinaryFormatter
is a poor choice in this case since it deserializes to a new instance of the exact same type as the serialized type.
Upvotes: 3
Reputation: 977
Without knowing your objects, the general answer is - you need to do a deep copy of your object. This isn't as easy as it looks on the surface if the object is complex. See StackOverflow - cloning objects
Upvotes: 0