Beispiel #1
0
        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
        }
Beispiel #2
0
 public static object Clone(this object original, ICloner fallbackCloner, bool tryPreserveInstances)
 {
     using (var context = CloningContext.New(fallbackCloner, tryPreserveInstances))
     {
         return(Clone(context, original));
     }
 }
Beispiel #3
0
        internal static object Clone(CloningContext context, object original)
        {
            object clone = null;

            CloneInto(context, ref clone, original);
            return(clone);
        }
Beispiel #4
0
        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;
        }
Beispiel #5
0
        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 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);
                        }
                    }
                }
            }
        }
Beispiel #7
0
        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);
            }
        }
Beispiel #8
0
 public virtual void FillClone(Type type, ref T clone, T original, CloningContext context)
 {
 }
Beispiel #9
0
 public override void FillClone(Type type, ref VariableDeclarations clone, VariableDeclarations original, CloningContext context)
 {
     foreach (var variable in original)
     {
         clone[variable.name] = variable.value.CloneViaFakeSerialization();
     }
 }
        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));
            }
        }
Beispiel #11
0
        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);
            }
        }
Beispiel #12
0
        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);
            }
        }