protected OperatorGraph(OperatorGraph original, Cloner cloner) : base(original, cloner) { operators = cloner.Clone(original.operators); initialOperator = cloner.Clone(original.initialOperator); visualizationInfo = cloner.Clone(original.visualizationInfo); Initialize(); }
public void TestCloningAllDeepCloneables() { PluginLoader.Assemblies.ToArray(); bool success = true; foreach (Type deepCloneableType in ApplicationManager.Manager.GetTypes(typeof(IDeepCloneable))) { // skip types that explicitely choose not to deep-clone every member if (excludedTypes.Contains(deepCloneableType)) continue; // test only types contained in HL plugin assemblies if (!PluginLoader.Assemblies.Contains(deepCloneableType.Assembly)) continue; // test only instantiable types if (deepCloneableType.IsAbstract || !deepCloneableType.IsClass) continue; IDeepCloneable item = null; try { item = (IDeepCloneable)Activator.CreateInstance(deepCloneableType, nonPublic: false); } catch { continue; } // no default constructor IDeepCloneable clone = null; try { clone = (IDeepCloneable)item.Clone(new Cloner()); } catch (Exception e) { TestContext.WriteLine(Environment.NewLine + deepCloneableType.FullName + ":"); TestContext.WriteLine("ERROR! " + e.GetType().Name + @" was thrown during cloning. All IDeepCloneable items with a default constructor should be cloneable when using that constructor!"); success = false; continue; } var intersections = CheckTotalInequality(item, clone).Where(x => x.GetType().FullName.StartsWith("HeuristicLab")); if (!intersections.Any()) continue; if (!ProcessEqualObjects(item, intersections)) success = false; } Assert.IsTrue(success, "There are potential errors in deep cloning objects."); }
private bool ProcessEqualObjects(IDeepCloneable item, IEnumerable<object> intersections) { bool success = true; bool headerWritten = false; foreach (object o in intersections) { string typeName = o.GetType().FullName; if (excludedTypes.Contains(o.GetType())) { //TestContext.WriteLine("Skipping excluded type " + typeName); } else if (o is IDeepCloneable) { string info = (o is IItem) ? ((IItem)o).ItemName + ((o is INamedItem) ? ", " + ((INamedItem)o).Name : String.Empty) : String.Empty; if (!headerWritten) { TestContext.WriteLine(Environment.NewLine + item.GetType().FullName + ":"); headerWritten = true; } TestContext.WriteLine("POTENTIAL ERROR! A DEEPCLONEABLE WAS NOT DEEP CLONED (" + info + "): " + typeName); success = false; } else { Array array = o as Array; if (array != null && array.Length == 0) continue; //arrays of length 0 are used inside empty collections if (!headerWritten) { TestContext.WriteLine(Environment.NewLine + item.GetType().FullName + ":"); headerWritten = true; } TestContext.WriteLine("WARNING: An object of type " + typeName + " is referenced in the original and in the clone."); } } return success; }
/// <summary> /// Initializes a new instance of <see cref="OperatorGraph"/>. /// </summary> public OperatorGraph() { operators = new OperatorSet(); initialOperator = null; visualizationInfo = null; Initialize(); }
/// <summary> /// Returns the clone of an deeply cloned item, if it was already cloned. /// </summary> /// <param name="original">The original object.</param> /// <returns>The clone of the given object, if it was already cloned; null otherwise</returns> public IDeepCloneable GetClone(IDeepCloneable original) { IDeepCloneable clone = null; mapping.TryGetValue(original, out clone); return(clone); }
/// <summary> /// Creates a deep clone of this repeated field. /// </summary> /// <remarks> /// If the field type is /// a message type, each element is also cloned; otherwise, it is /// assumed that the field type is primitive (including string and /// bytes, both of which are immutable) and so a simple copy is /// equivalent to a deep clone. /// </remarks> /// <returns>A deep clone of this repeated field.</returns> public RepeatedField <T> Clone() { int len = Count; if (len > 0) { bool isDeepCloner = base[0] is IDeepCloneable <T>; RepeatedField <T> clone = new RepeatedField <T>(len); if (isDeepCloner) { for (int i = 0; i < len; i++) { IDeepCloneable <T> item = base[i] as IDeepCloneable <T>; if (item != null) { clone.Add(item.Clone()); } else { clone.Add(base[i]); } } } else { for (int i = 0; i < len; i++) { clone.Add(base[i]); } } return(clone); } return(new RepeatedField <T>()); }
public T Get() { var path = GetPath(); //Console.WriteLine(string.Join(",", path)); object container = this; for (int i = 0; i < path.Count; ++i) { if (i < path.Count - 1) { container = container .GetType() .GetField(path[i], BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(container); } else { T value = (T)container .GetType() .GetField(path[i], BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(container); IDeepCloneable <T> cloneable = value as IDeepCloneable <T>; if (cloneable == null) { return(value); } return(cloneable.Clone()); } } throw new Exception("Something went wrong"); }
public IDeepCloneable Clone(IDeepCloneable obj) { if (obj == null) { return(null); } IDeepCloneable clone; if (cache.TryGetValue(obj, out clone)) { return(clone); } else { return(obj.Clone(this)); } }
protected Constraint(Constraint original, Cloner cloner) : base(original, cloner) { constrainedValue = null; //mkommend: intentionally set to null; IDeepCloneable constraintDataDeepCloneable = original.constraintData as IDeepCloneable; ICloneable constraintDataCloneable = original.constraintData as ICloneable; if (constraintDataDeepCloneable != null) { constraintData = cloner.Clone(constraintDataDeepCloneable); } else if (constraintDataCloneable != null) { constraintData = constraintDataCloneable.Clone(); } else { constraintData = original.constraintData; } constraintOperation = original.constraintOperation; }
public void RegisterClonedObject(IDeepCloneable original, IDeepCloneable clone) { cache.Add(original, clone); }
/// <summary> /// Used to deep clone any reference properties on the object (should be done after a MemberwiseClone for which the outcome is 'output') /// </summary> /// <param name="input"></param> /// <param name="output"></param> /// <returns></returns> public static void DeepCloneRefProperties(IDeepCloneable input, IDeepCloneable output) { var inputType = input.GetType(); var outputType = output.GetType(); if (inputType != outputType) { throw new InvalidOperationException("Both the input and output types must be the same"); } //get the property metadata from cache so we only have to figure this out once per type var refProperties = PropCache.GetOrAdd(inputType, type => inputType.GetProperties() .Select <PropertyInfo, ClonePropertyInfo?>(propertyInfo => { if ( //is not attributed with the ignore clone attribute propertyInfo.GetCustomAttribute <DoNotCloneAttribute>() != null //reference type but not string || propertyInfo.PropertyType.IsValueType || propertyInfo.PropertyType == typeof(string) //settable || propertyInfo.CanWrite == false //non-indexed || propertyInfo.GetIndexParameters().Any()) { return(null); } if (TypeHelper.IsTypeAssignableFrom <IDeepCloneable>(propertyInfo.PropertyType)) { return(new ClonePropertyInfo(propertyInfo) { IsDeepCloneable = true }); } if (TypeHelper.IsTypeAssignableFrom <IEnumerable>(propertyInfo.PropertyType) && TypeHelper.IsTypeAssignableFrom <string>(propertyInfo.PropertyType) == false) { if (propertyInfo.PropertyType.IsGenericType && (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable <>) || propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection <>) || propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList <>))) { //if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<> var genericType = typeof(List <>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments()); return(new ClonePropertyInfo(propertyInfo) { GenericListType = genericType }); } if (propertyInfo.PropertyType.IsArray || (propertyInfo.PropertyType.IsInterface && propertyInfo.PropertyType.IsGenericType == false)) { //if its an array, we'll create a list to work with first and then convert to array later //otherwise if its just a regular derivative of IEnumerable, we can use a list too return(new ClonePropertyInfo(propertyInfo) { GenericListType = typeof(List <object>) }); } //skip instead of trying to create instance of abstract or interface if (propertyInfo.PropertyType.IsAbstract || propertyInfo.PropertyType.IsInterface) { return(null); } //its a custom IEnumerable, we'll try to create it try { var custom = Activator.CreateInstance(propertyInfo.PropertyType); //if it's an IList we can work with it, otherwise we cannot var newList = custom as IList; if (newList == null) { return(null); } return(new ClonePropertyInfo(propertyInfo) { GenericListType = propertyInfo.PropertyType }); } catch (Exception) { //could not create this type so we'll skip it return(null); } } return(new ClonePropertyInfo(propertyInfo)); }) .Where(x => x.HasValue) .Select(x => x.Value) .ToArray()); foreach (var clonePropertyInfo in refProperties) { if (clonePropertyInfo.IsDeepCloneable) { //this ref property is also deep cloneable so clone it var result = (IDeepCloneable)clonePropertyInfo.PropertyInfo.GetValue(input, null); if (result != null) { //set the cloned value to the property clonePropertyInfo.PropertyInfo.SetValue(output, result.DeepClone(), null); } } else if (clonePropertyInfo.IsList) { var enumerable = (IEnumerable)clonePropertyInfo.PropertyInfo.GetValue(input, null); if (enumerable == null) { continue; } var newList = (IList)Activator.CreateInstance(clonePropertyInfo.GenericListType); var isUsableType = true; //now clone each item foreach (var o in enumerable) { //first check if the item is deep cloneable and copy that way var dc = o as IDeepCloneable; if (dc != null) { newList.Add(dc.DeepClone()); } else if (o is string || o.GetType().IsValueType) { //check if the item is a value type or a string, then we can just use it newList.Add(o); } else { //this will occur if the item is not a string or value type or IDeepCloneable, in this case we cannot // clone each element, we'll need to skip this property, people will have to manually clone this list isUsableType = false; break; } } //if this was not usable, skip this property if (isUsableType == false) { continue; } if (clonePropertyInfo.PropertyInfo.PropertyType.IsArray) { //need to convert to array var arr = (object[])Activator.CreateInstance(clonePropertyInfo.PropertyInfo.PropertyType, newList.Count); for (int i = 0; i < newList.Count; i++) { arr[i] = newList[i]; } //set the cloned collection clonePropertyInfo.PropertyInfo.SetValue(output, arr, null); } else { //set the cloned collection clonePropertyInfo.PropertyInfo.SetValue(output, newList, null); } } } }
/// <summary> /// Checks if a clone is already registered for a given deeply cloneable item. /// </summary> /// <param name="item">The original object.</param> /// <returns>True if a clone is already registered for the given item; false otherwise</returns> public bool ClonedObjectRegistered(IDeepCloneable item) { return(mapping.ContainsKey(item)); }
/// <summary> /// Registers a new clone for a given deeply cloneable object. /// </summary> /// <param name="item">The original object.</param> /// <param name="clone">The clone of the original object.</param> public void RegisterClonedObject(IDeepCloneable item, IDeepCloneable clone) { mapping.Add(item, clone); }