public CopyableNumbersWithSettings(int a, float b, ICopyOverrideSettings settings) : base(a, b, settings) { _a = a; _b = b; _settings = settings; }
/// <summary> /// Creates a copy of the object. /// </summary> /// <param name="instance">The object to be copied.</param> /// <param name="expectedType">The type that should be found.</param> /// <param name="overrideSettings">Settings to override the copy logic.</param> /// <typeparam name="T">The type of the instance given.</typeparam> /// <returns>A deep copy of the object.</returns> public static T Copy <T>(this T instance, ICopyOverrideSettings overrideSettings) { return(instance.Copy(typeof(T), overrideSettings)); }
/// <summary> /// Creates a deep copy of the object using the supplied object as a target for the copy operation. /// </summary> /// <param name="instance">The object to be copied.</param> /// <param name="copy">The object to copy values to. All fields of this object will be overwritten.</param> /// <param name="expectedType">The type that should be found.</param> /// <param name="overrideSettings">Settings to override the copy logic.</param> /// <typeparam name="T">The type of the instance given.</typeparam> /// <returns>A deep copy of the object.</returns> public static T Copy <T>(this T instance, T copy, Type expectedType, ICopyOverrideSettings overrideSettings) { return(instance.Copy(copy, expectedType, new[] { overrideSettings })); }
/// <summary> /// Creates a deep copy of an object using the supplied dictionary of visited objects as /// a source of objects already encountered in the copy traversal. The dictionary of visited /// objects is used for holding objects that have already been copied, to avoid erroneous /// duplication of parts of the object graph. /// </summary> /// <param name="instance">The object to be copied.</param> /// <param name="visited">The graph of objects visited so far.</param> /// <param name="copy">The object to copy to.</param> /// <param name="expectedType">The type that should be found.</param> /// <param name="overrideSettings">Settings to override the copy logic.</param> /// <typeparam name="T">The type of the instance given.</typeparam> /// <returns>The copied object.</returns> private static T Clone <T>(this T instance, VisitedGraph visited, T copy, Type expectedType, IList <ICopyOverrideSettings> overrideSettings = null) { if (ShouldUseVisitedGraph(overrideSettings)) { if (visited.ContainsKey(instance)) { return((T)visited[instance]); } else { visited.Add(instance, copy); } } Type type = instance.GetType(); string instanceTypeNameString = type.FullName; bool shouldSkip = CheckIfShouldSkip(overrideSettings, type.FullName, false); if (shouldSkip) { return(default(T)); } BindingFlags flags = overrideSettings?.Any(s => s.IncludeNonPublic) ?? true ? BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance : BindingFlags.Public | BindingFlags.Instance; while (type != null) { List <ICopyOverrideSettings> currentSettings = overrideSettings?.Where(s => s.ContainingClassType.IsAssignableFrom(type)) .ToList() ?? new List <ICopyOverrideSettings>(); foreach (FieldInfo field in type.GetFields(flags)) { shouldSkip = false; shouldSkip = CheckIfShouldSkip(overrideSettings, field?.FieldType?.FullName, shouldSkip); if (shouldSkip || ShouldSkipDotNet(type, field.FieldType, field.Name)) { continue; } object value = field.GetValue(instance); ICopyOverrideSettings currentOverride = currentSettings.SingleOrDefault(s => s.FieldValueOverrideType.IsAssignableFrom(field.FieldType) && s.ContainingClassType.IsAssignableFrom(type) && s.AffectedFieldName == field.Name); try { if (currentOverride != null) { if (!currentOverride.ShouldSkipOverrideInsteadOfSet) { var settableValue = currentOverride.UseFieldValueOverrideFunction ? currentOverride.FieldValueOverrideFunction(instance) : currentOverride.FieldValueOverride; field.SetValue(copy, settableValue); if (currentOverride.OnlyOverrideFirst) { overrideSettings.Remove(overrideSettings.Single(s => s.AffectedFieldName == s.AffectedFieldName && s.ContainingClassType == s.ContainingClassType && s.FieldValueOverride == s.FieldValueOverride && s.FieldValueOverrideType == s.FieldValueOverrideType && s.OnlyOverrideFirst == s.OnlyOverrideFirst)); } } } else if (ShouldUseVisitedGraph(overrideSettings) && visited.ContainsKey(value)) { var settableValue = visited[value]; field.SetValue(copy, settableValue); } else { var settableValue = value.Clone(visited, field.FieldType, overrideSettings); field.SetValue(copy, settableValue); } } catch (Exception ex) { if (ShouldThrow(overrideSettings, field?.FieldType?.FullName, true, ex)) { throw; } } } foreach (PropertyInfo propertyInfo in type.GetProperties(flags)) { if (!propertyInfo.CanRead || !propertyInfo.CanWrite) { continue; } shouldSkip = false; shouldSkip = CheckIfShouldSkip(overrideSettings, propertyInfo?.PropertyType?.FullName, shouldSkip); ParameterInfo[] propParameters = propertyInfo.GetIndexParameters(); if (!shouldSkip && propParameters?.Where(pp => !pp.IsOptional).Count() > 0) { shouldSkip = true; } if (shouldSkip || ShouldSkipDotNet(type, propertyInfo.PropertyType, propertyInfo.Name)) { continue; } object value = propertyInfo.GetValue(instance); ICopyOverrideSettings currentOverride = currentSettings.SingleOrDefault(s => s.FieldValueOverrideType.IsAssignableFrom(propertyInfo.PropertyType) && s.ContainingClassType.IsAssignableFrom(type) && s.AffectedFieldName == propertyInfo.Name); try { if (currentOverride != null) { if (!currentOverride.ShouldSkipOverrideInsteadOfSet) { var settableValue = currentOverride.UseFieldValueOverrideFunction ? currentOverride.FieldValueOverrideFunction(instance) : currentOverride.FieldValueOverride; propertyInfo.SetValue(copy, settableValue); if (currentOverride.OnlyOverrideFirst) { overrideSettings.Remove(overrideSettings.Single(s => s.AffectedFieldName == s.AffectedFieldName && s.ContainingClassType == s.ContainingClassType && s.FieldValueOverride == s.FieldValueOverride && s.FieldValueOverrideType == s.FieldValueOverrideType && s.OnlyOverrideFirst == s.OnlyOverrideFirst)); } } } else if (ShouldUseVisitedGraph(overrideSettings) && visited.ContainsKey(value)) { var settableValue = visited[value]; propertyInfo.SetValue(copy, settableValue); } else { var settableValue = value.Clone(visited, propertyInfo.PropertyType, overrideSettings); propertyInfo.SetValue(copy, settableValue); } } catch (Exception ex) { if (ShouldThrow(overrideSettings, propertyInfo?.PropertyType?.FullName, true, ex)) { throw; } } } type = type.BaseType; } // call the post copy actions if (overrideSettings?.Any(s => s?.PostCopyActions != null) ?? false) { foreach (ICopyOverrideSettings setting in overrideSettings) { if (!(setting?.PostCopyActions?.Any() ?? false)) { continue; } // try the exact post copy action if (setting.PostCopyActions.ContainsKey(copy.GetType())) { setting.PostCopyActions[copy.GetType()](instance, copy, expectedType); } // try the default post copy action else if (setting.PostCopyActions.ContainsKey(setting.DefaultPostActionType)) { setting.PostCopyActions[setting.DefaultPostActionType](instance, copy, expectedType); } } } return(copy); }