/// <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);
            }
        }