private static void SearchAndReplaceAggregates(object root) { var visitedItems = new HashSet <object>(); var queue = new Queue <object>(); queue.Enqueue(root); while (queue.Count > 0) { var inst = queue.Dequeue(); if (IsInstanceOfSimpleType(inst)) { continue; } // geometries var baseType = inst.GetType().BaseType; if ((baseType != null && baseType.Name == "Geometry") && inst is ICloneable) { continue; } // gdi stuff if (inst.GetType().FullName.StartsWith("System.Drawing.") && inst is ICloneable) { continue; } if (visitedItems.Contains(inst)) { continue; } visitedItems.Add(inst); foreach (var pi in GetAllAccessiblePropertiesForType(inst.GetType())) { object value; if (!GetValue(inst, pi, out value)) { continue; } if (AttributeInfoCache.IsAggregation(pi)) { if (value is IList) //lists are special case of aggregation { var clone = (IList)value; //already cloned..just not the values for (var i = 0; i < clone.Count; i++) { var item = clone[i]; var clonedItem = cloneStore.GetExistingCloneFor(item); if (clonedItem != null) { ReplaceListItem(clone, i, clonedItem); } } } else { var clone = cloneStore.GetExistingCloneFor(value); if (clone != null) { SetValue(pi, inst, clone); } } } else { queue.Enqueue(value); } } if (inst is IList) { var list = inst as IList; foreach (var item in list) { queue.Enqueue(item); } } } }
private static void DeepClonePropertiesAndFields(object inst, object clone) { var aggregationProperties = new List <string>(); // set in all properties (to trigger subscription etc) foreach (var pi in OrderByComplexity(GetAllAccessiblePropertiesForType(inst.GetType()))) { object value; if (!GetValue(inst, pi, out value)) { continue; } object clonedValue; if (AttributeInfoCache.IsAggregation(pi)) //if aggregate: only set existing clones { aggregationProperties.Add(pi.Name); if (ProcessAggregateMember(value, clone, pi, out clonedValue)) { continue; } } else { clonedValue = DeepCloneCore(value); } SetValue(pi, clone, clonedValue); } // set in all fields that we missed so far foreach (var fieldAndValue in GetNonInfrastructureFields(inst)) { var fi = fieldAndValue.Key; var value = fieldAndValue.Value; if (!ShouldReplaceValue(value)) { continue; } if (!IsInstanceOfSimpleType(value)) { if (cloneStore.IsAlreadyClonedInstance(value)) { continue; } } object clonedValue; if (aggregationProperties.Any(p => IsFieldForProperty(fi, p))) { if (ProcessAggregateMember(value, clone, fi, out clonedValue)) { continue; } } else { clonedValue = DeepCloneCore(value); } SetValue(fi, clone, clonedValue); } }