internal static object Clone(CloningContext context, object original)
        {
            object clone = null;

            CloneInto(context, ref clone, original);
            return(clone);
        }
        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.clones.TryGetValue(original, out var existingClone))
            {
                clone = existingClone;
                return;
            }

            var cloner = GetCloner(original, type, context.fallbackCloner);

            if (clone == null)
            {
                clone = cloner.ConstructClone(type, original);
            }

            context.clones.Add(original, clone);
            cloner.BeforeClone(type, original);
            cloner.FillClone(type, ref clone, original, context);
            cloner.AfterClone(type, clone);
            context.clones[original] = clone;             // In case the reference changed, for example in arrays
        }
 public static void CloneInto(this object original, ref object clone, ICloner fallbackCloner, bool tryPreserveInstances)
 {
     using (var context = CloningContext.New(fallbackCloner, tryPreserveInstances))
     {
         CloneInto(context, ref clone, original);
     }
 }
 public static object Clone(this object original, ICloner fallbackCloner, bool tryPreserveInstances)
 {
     using (var context = CloningContext.New(fallbackCloner, tryPreserveInstances))
     {
         return(Clone(context, original));
     }
 }
        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 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 void CloneInto(this object original, ref object clone, ICloner fallbackCloner, bool tryPreserveInstances, out Dictionary <object, object> clones)
 {
     using (var context = CloningContext.New(fallbackCloner, tryPreserveInstances))
     {
         CloneInto(context, ref clone, original);
         clones = new Dictionary <object, object>(context.clones);
     }
 }
 public static object Clone(this object original, ICloner fallbackCloner, bool tryPreserveInstances, out Dictionary <object, object> clones)
 {
     using (var context = CloningContext.New(fallbackCloner, tryPreserveInstances))
     {
         var clone = Clone(context, original);
         clones = new Dictionary <object, object>(context.clones);
         return(clone);
     }
 }
        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);
                        }
                    }
                }
            }
        }
Пример #10
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);
            }
        }
 public virtual void FillClone(Type type, ref T clone, T original, CloningContext context)
 {
 }
Пример #12
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);
            }
        }
Пример #13
0
		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(clone, Cloning.Clone(context, item));
			}
		}
Пример #14
0
        public override void FillClone(Type type, ref Gradient clone, Gradient original, CloningContext context)
        {
            clone.SetKeys(original.colorKeys, original.alphaKeys);

            try
            {
                clone.mode = original.mode;
            }
            catch (UnityException)
            {
                // We're off the main thread, nothing we can do
            }
        }
Пример #15
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);
            }
        }