internal static void CloneInto(CloningContext context, ref object clone, object original) { if (original == null) { clone = null; return; } var type = original.GetType(); if (Skippable(type)) { clone = original; return; } if (context.clonings.ContainsKey(original)) { clone = context.clonings[original]; return; } var cloner = GetCloner(original, type, context.fallbackCloner); if (clone == null) { clone = cloner.ConstructClone(type, original); } context.clonings.Add(original, clone); cloner.BeforeClone(type, original); cloner.FillClone(type, ref clone, original, context); cloner.AfterClone(type, clone); context.clonings[original] = clone; // In case the reference changed, for example in arrays }
public override void FillClone(Type type, ref IList clone, IList original, CloningContext context) { if (context.tryPreserveInstances) { for (int i = 0; i < original.Count; i++) { var originalItem = original[i]; if (i < clone.Count) { // The clone has at least as many items, we can try to preserve its instances. var cloneItem = clone[i]; Cloning.CloneInto(context, ref cloneItem, originalItem); clone[i] = cloneItem; } else { // The clone has less items than the original, we have to add a new item. clone.Add(Cloning.Clone(context, originalItem)); } } } else { // Avoiding foreach to avoid enumerator allocation for (int i = 0; i < original.Count; i++) { var originalItem = original[i]; clone.Add(Cloning.Clone(context, originalItem)); } } }
public static object Clone(this object original, ICloner fallbackCloner, bool tryPreserveInstances) { using (var context = CloningContext.New(fallbackCloner, tryPreserveInstances)) { return(Clone(context, original)); } }
internal static object Clone(CloningContext context, object original) { object clone = null; CloneInto(context, ref clone, original); return(clone); }
void ICloner.FillClone(Type type, ref object clone, object original, CloningContext context) { var _instance = (T)clone; FillClone(type, ref _instance, (T)original, context); clone = _instance; }
public override void FillClone(Type type, ref object clone, object original, CloningContext context) { if (PlatformUtility.supportsJit) { foreach (var accessor in GetOptimizedAccessors(type)) { if (context.tryPreserveInstances) { var cloneProperty = accessor.GetValue(clone); Cloning.CloneInto(context, ref cloneProperty, accessor.GetValue(original)); accessor.SetValue(clone, cloneProperty); } else { accessor.SetValue(clone, Cloning.Clone(context, accessor.GetValue(original))); } } } else { foreach (var accessor in GetAccessors(type)) { if (accessor is FieldInfo) { var field = (FieldInfo)accessor; if (context.tryPreserveInstances) { var cloneProperty = field.GetValue(clone); Cloning.CloneInto(context, ref cloneProperty, field.GetValue(original)); field.SetValue(clone, cloneProperty); } else { field.SetValue(clone, Cloning.Clone(context, field.GetValue(original))); } } else if (accessor is PropertyInfo) { var property = (PropertyInfo)accessor; if (context.tryPreserveInstances) { var cloneProperty = property.GetValue(clone, null); Cloning.CloneInto(context, ref cloneProperty, property.GetValue(original, null)); property.SetValue(clone, cloneProperty, null); } else { property.SetValue(clone, Cloning.Clone(context, property.GetValue(original, null)), null); } } } } }
public override void FillClone(Type type, ref Array clone, Array original, CloningContext context) { var length = original.GetLength(0); clone = Array.CreateInstance(type.GetElementType(), length); for (int i = 0; i < length; i++) { clone.SetValue(Cloning.Clone(context, original.GetValue(i)), i); } }
public override void FillClone(Type type, ref IEnumerable clone, IEnumerable original, CloningContext context) { var addMethod = GetAddMethod(type); if (addMethod == null) { throw new InvalidOperationException($"Cannot instantiate enumerable type '{type}' because it does not provide an add method."); } // No way to preserve instances here foreach (var item in original) { addMethod.Invoke(item, Cloning.Clone(context, item)); } }
public virtual void FillClone(Type type, ref T clone, T original, CloningContext context) { }
public override void FillClone(Type type, ref AnimationCurve clone, AnimationCurve original, CloningContext context) { for (int i = 0; i < clone.length; i++) { clone.RemoveKey(i); } foreach (var key in original.keys) { clone.AddKey(key); } }
public override void FillClone(Type type, ref IDictionary clone, IDictionary original, CloningContext context) { // No support for instance preservation here, but none in FS either, so it shouldn't matter var originalEnumerator = original.GetEnumerator(); while (originalEnumerator.MoveNext()) { var originalKey = originalEnumerator.Key; var originalValue = originalEnumerator.Value; var cloneKey = Cloning.Clone(context, originalKey); var cloneValue = Cloning.Clone(context, originalValue); clone.Add(cloneKey, cloneValue); } }