/// <summary> /// Legt <paramref name="property"/> in <paramref name="destinationObject"/> auf den Wert von <paramref name="sourceObject"/> /// </summary> /// <typeparam name="T1"></typeparam> /// <param name="destinationObject"></param> /// <param name="sourceObject"></param> /// <param name="property"></param> private static void SetPropertyValue <T1>(T1 destinationObject, object sourceObject, PropertyInfo property) { try { if (property.EvaluateAttribute <IgnoreAtMerging>(IgnoreAtMerging.DefaultValue)) // If true This property is ignored { return; } if (!property.EvaluateAttribute <IsMergeable>(IsMergeable.DefaultValue)) //!AttributeEvaluator.IsMergeable(Attribute.GetCustomAttributes(property))) { property.SetValue(destinationObject, property.GetValue(sourceObject, null), null); } // Falls die Property im Ziel nicht initialisiert ist -> kopieren else if (property.GetValue(destinationObject) == null) // Irgendein ISKills lässt das hier abstürzen { property.SetValue(destinationObject, property.GetValue(sourceObject, null), null); } // Falls beide Properties informationen enthalten -> zusammenführen versuchen else if (property.GetValue(sourceObject) != null && property.GetValue(destinationObject) != null) { var initialValue = property.GetValue(destinationObject); var mergedInformation = MergeObjects(initialValue, property.GetValue(sourceObject)); if (!initialValue.Equals(mergedInformation)) // Only set if value is new { property.SetValue(destinationObject, mergedInformation, null); } } } catch (TargetInvocationException e) { Debug.WriteLine(e); } catch (TargetParameterCountException e) { Debug.WriteLine(e); } catch (Exception exception) { ObjectMergerLogger.GetInstance().Error(exception); } }
/// <summary> /// Fügt Informationen von mehreren Objekten in ein neues Objekt ein /// ACHTUNG !!!! Diese Funktion verändert im momentanen Zustand den Übergabeparameter !!!! /// </summary> /// <param name="destination"></param> /// <param name="source"></param> /// <param name="parent"></param> /// <returns></returns> public static T1 MergeObjects <T1>(T1 destination, object source, object parent = null) { T1 result; // = Activator.CreateInstance<T>(); if (ReferenceEquals(destination, source)) { return(destination); } else if (destination == null && source == null) { return(default(T1)); } else if (source == null) { return(destination); } else if (destination == null) { return((T1)source); } // Replace one Object if they aren't Mergeable else if (!destination.GetType().EvaluateAttribute <IsMergeable>(IsMergeable.DefaultValue)) //!AttributeEvaluator.IsMergeable(new Type[]{destination.GetType()})) // Falls die übergebenen Klassen nicht mit dem IsMergeable attribut assoziiert wurden { // If destination is default constructed, do copy new one if (destination.IsDefaultConstructed() && !source.IsDefaultConstructed()) { ObjectMergerLogger.GetInstance().Debug("Overriding \"{0}\" with new value \"{1}\"", destination, source); return((T1)source); } // If source is default constructed do not copy new one else if (source.IsDefaultConstructed()) { return(destination); } // if nothing is default, take the new one else { return((T1)source); } } Type destinationType = destination.GetType(); Type sourceType = source.GetType(); Type commonType = destinationType.FindEqualTypeWith(sourceType); // Resolve hierarchy recursions var redirectedSourceItems = RedirectRecursions(source, null); var redirectedDestinationItems = RedirectRecursions(destination, null); // Falls das Objekt ein Primitiver datentyp ist // Wird als erstes abgeprüft, da dies der häufigste Fall ist if (destinationType.IsValueType) { // Falls der Datentyp Primitive ist, wird der neue Wert genommen result = (T1)source; } else if (destinationType == typeof(string)) // Da Strings vom Type IEnumerable<Char> sind, müssen diese vorher abgefangen werden { result = (T1)source; } else if (typeof(MemberInfo).IsAssignableFrom(commonType)) // Member Infos machen immer wieder probleme { string parentString = parent != null?parent.ToString() : "unknown parent"; string memberString = ((MemberInfo)source).Name; ObjectMergerLogger.GetInstance().Warning("Member info \"{0}\" in \"{1}\" was copied", memberString, parentString); result = (T1)source; } else if (typeof(Delegate).IsAssignableFrom(commonType)) // Delegaten können zwar kopiert werden, sind aber evtl. nicht sinnvoll, da sie ihren ursprünglichen Besitzer referenzieren { string parentString = parent != null?parent.ToString() : "unknown parent"; string memberString = ((Delegate)source).Method.Name; ObjectMergerLogger.GetInstance().Warning( "Member info \"{0}\" in \"{1}\" was copied. \n The Reference to its original parent may remain.", memberString, parentString); result = (T1)source; } else if (commonType.IsGenericType && typeof(Dictionary <,>) == commonType.GetGenericTypeDefinition()) //Dictionaries behandeln { Type enumerationType1 = commonType.GetGenericArguments()[0]; Type enumerationType2 = commonType.GetGenericArguments()[1]; // I want to create a List<?> containing the existing // object, but strongly typed to the "right" type depending // on the type of the value of x MethodInfo method = typeof(MergingHelper).GetMethod("MergeDictionaries", BindingFlags.NonPublic | BindingFlags.Static); // todo: String per referenz ermitteln //MethodInfo method = SymbolExtensions.GetMethodInfo(() => MergingHelper.MergeDictionaries<T,T>(destination, source)); method = method.MakeGenericMethod(new Type[] { enumerationType1, enumerationType2 }); var mergedIEnumerable = method.Invoke(null, new[] { destination, source }); result = (T1)mergedIEnumerable; } // Allgemeine Methode für Listen else if (typeof(ICollection).IsAssignableFrom(commonType)) //(destinationType == typeof(IEnumerable<object>)) { Type enumerationType = destinationType.GetEnumerableType(); MethodInfo method = typeof(MergingHelper).GetMethod("MergeIEnumerables", BindingFlags.NonPublic | BindingFlags.Static); // todo: String per referenz ermitteln //MethodInfo method = // SymbolExtensions.GetMethodInfo(() => MergingHelper.MergeIEnumerables(destination, source, true)); // Sowohl der Container, als auch die beinhalteten Elemente müssen Duplizierung zulassen bool duplicatesAllowed = destinationType.EvaluateAttribute <DuplicatesAllowed>(DuplicatesAllowed.DefaultValue) && enumerationType.EvaluateAttribute <DuplicatesAllowed>(DuplicatesAllowed.DefaultValue); method = method.MakeGenericMethod(new Type[] { enumerationType }); var mergedIEnumerable = method.Invoke(null, new[] { destination, source, duplicatesAllowed }); // todo : Attribute Container übergeben, damit das flexibler ist if (commonType.GetConstructor(new[] { mergedIEnumerable.GetType() }) != null) { result = (T1)Activator.CreateInstance(commonType, new object[] { mergedIEnumerable }); } else { result = (T1)mergedIEnumerable; } } // Ansonsten ist der Datentyp weder Primitiv noch eine Liste, somit mir rekursiv weiter das Standardverfahren angewendet else { result = MergeObjectFields(destination, source); result = MergeObjectProperties(result, source); } RedirectRecursions(redirectedDestinationItems, destination); RedirectRecursions(redirectedSourceItems, source); return(result); }
private IEnumerable <ObjectTreeItem> CreateChildLayer() { if (Item == null) { yield break; } else if (Item.GetType().IsPrimitive) { yield break; } else if (TypesNotToParse.Any(type => type == Item.GetType())) { yield break; } else if (TypesNotToParse.Any(type => type.IsInstanceOfType(Item))) { yield break; } else if ( // handle all IEnumberable types from mscorlib as IEnumberables (Item is IEnumerable && Item.GetType().Assembly.GetName().Name == "mscorlib") || // handle all generic types, which derive from special IEnumerables as IEnumberable (Item.GetType().IsGenericType&& SpecialIEnumberables.Any(type => type.IsAssignableFrom(Item.GetType().GetGenericTypeDefinition()))) || // handle all self-defined-non-generic types, which derive from special IEnumerables as IEnumberable (SpecialIEnumberables.Any(type => { var baseType = Item.GetType().FindGenericBaseClassWith(type); return(baseType != null && typeof(IEnumerable).IsAssignableFrom(baseType)); })) ) { foreach (var listEntry in (IEnumerable)Item) { var childTreeItem = new ObjectTreeItem(listEntry); childTreeItem.Parent = this; //childTreeItem.MemberInfo = fieldInfo; yield return(childTreeItem); } yield break; } // Parse fields foreach (var fieldInfo in Item.GetType().GetFields()) { var childValue = fieldInfo.GetValue(Item); var childTreeItem = new ObjectTreeItem(childValue); childTreeItem.Parent = this; childTreeItem.MemberInfo = fieldInfo; yield return(childTreeItem); } // parse Properties foreach (var propertyInfo in Item.GetType().GetProperties().Where(info => info.CanRead)) { object childValue = null; try { childValue = propertyInfo.GetValue(Item); } catch (TargetInvocationException e) { Debug.WriteLine(e); } catch (TargetParameterCountException e) { Debug.WriteLine(e); } catch (Exception exception) { ObjectMergerLogger.GetInstance().Error(exception); } var childTreeItem = new ObjectTreeItem(childValue); childTreeItem.Parent = this; childTreeItem.MemberInfo = propertyInfo; yield return(childTreeItem); } }