public ConfigurationElementCollection GetMergedElementCollection()
            {
                if (mergeableLocalElement == null)
                {
                    return(localCollection);
                }
                if (localCollection.EmitClear)
                {
                    return(localCollection);
                }

                List <ConfigurationElement> elementsFromParent = parentCollection.Cast <ConfigurationElement>().ToList();

                foreach (ConfigurationElement elementFromLocal in localCollection.Cast <ConfigurationElement>())
                {
                    var keyPredicate = CreateMatchKeyPredicate(elementFromLocal);
                    ConfigurationElement matchingElement = elementsFromParent.Where(keyPredicate).FirstOrDefault();

                    if (matchingElement != null)
                    {
                        ConfigurationElementMerge elementMerge  = new ConfigurationElementMerge(matchingElement, elementFromLocal);
                        ConfigurationElement      mergedElement = elementMerge.GetMergedElement();
                        int index = elementsFromParent.IndexOf(matchingElement);
                        elementsFromParent.RemoveAt(index);
                        elementsFromParent.Insert(index, mergedElement);
                    }
                    else
                    {
                        elementsFromParent.Add(elementFromLocal);
                    }
                }

                mergeableLocalElement.ResetCollection(elementsFromParent);
                return(localCollection);
            }
            public ConfigurationElementCollectionMerge(ConfigurationElementCollection parentCollection, ConfigurationElementCollection localCollection)
            {
                this.parentCollection = parentCollection;

                ConfigurationElementMerge elementMerge = new ConfigurationElementMerge(parentCollection, localCollection);

                this.localCollection = (ConfigurationElementCollection)elementMerge.GetMergedElement();

                this.mergeableLocalElement = MergeableConfigurationCollectionFactory.GetCreateMergeableCollection(localCollection);

                //TODO : what to do around: localCollection.CollectionType
            }
            public ConfigurationElement GetMergedElement()
            {
                Dictionary <string, PropertyInformation> localProperties  = localElement.ElementInformation.Properties.OfType <PropertyInformation>().ToDictionary(x => x.Name);
                Dictionary <string, PropertyInformation> parentProperties = parentElement.ElementInformation.Properties.OfType <PropertyInformation>().ToDictionary(x => x.Name);

                foreach (string propertyName in localProperties.Keys)
                {
                    PropertyInformation localProperty, parentProperty;
                    localProperty  = localProperties[propertyName];
                    parentProperty = parentProperties[propertyName];

                    if (typeof(ConfigurationElement).IsAssignableFrom(localProperty.Type))
                    {
                        //either a collection or regular element

                        if (localProperty.Value == null)
                        {
                            localProperty.Value = parentProperty.Value;
                            continue;
                        }

                        if (parentProperty.Value != null)
                        {
                            if (typeof(ConfigurationElementCollection).IsAssignableFrom(localProperty.Type))
                            {
                                ConfigurationElementCollectionMerge merge = new ConfigurationElementCollectionMerge((ConfigurationElementCollection)parentProperty.Value, (ConfigurationElementCollection)localProperty.Value);
                                localProperty.Value = merge.GetMergedElementCollection();
                            }
                            else
                            {
                                ConfigurationElementMerge merge = new ConfigurationElementMerge((ConfigurationElement)parentProperty.Value, (ConfigurationElement)localProperty.Value);
                                localProperty.Value = merge.GetMergedElement();
                            }
                        }
                    }
                    else
                    {
                        //just a regular property

                        if (ShouldOverrideLocalProperty(localProperty, parentProperty))
                        {
                            localProperty.Value = parentProperty.Value;
                        }
                    }
                }


                return(localElement);
            }
            public ConfigurationSection GetMergedSection()
            {
                ConfigurationElementMerge elementMerge = new ConfigurationElementMerge(parentSection, localSection);

                return(elementMerge.GetMergedElement() as ConfigurationSection);
            }
            public ConfigurationElementCollection GetMergedElementCollection()
            {
                if (mergeableLocalElement == null) return localCollection;
                if (localCollection.EmitClear) return localCollection;

                List<ConfigurationElement> elementsFromParent = parentCollection.Cast<ConfigurationElement>().ToList();

                foreach (ConfigurationElement elementFromLocal in localCollection.Cast<ConfigurationElement>())
                {
                    var keyPredicate = CreateMatchKeyPredicate(elementFromLocal);
                    ConfigurationElement matchingElement = elementsFromParent.Where(keyPredicate).FirstOrDefault();

                    if (matchingElement != null)
                    {
                        ConfigurationElementMerge elementMerge = new ConfigurationElementMerge(matchingElement, elementFromLocal);
                        ConfigurationElement mergedElement = elementMerge.GetMergedElement();
                        int index = elementsFromParent.IndexOf(matchingElement);
                        elementsFromParent.RemoveAt(index);
                        elementsFromParent.Insert(index, mergedElement);
                    }
                    else
                    {
                        elementsFromParent.Add(elementFromLocal);
                    }
                }

                mergeableLocalElement.ResetCollection(elementsFromParent);
                return localCollection;
            }
            public ConfigurationElementCollectionMerge(ConfigurationElementCollection parentCollection, ConfigurationElementCollection localCollection)
            {
                this.parentCollection = parentCollection;
                
                ConfigurationElementMerge elementMerge = new ConfigurationElementMerge(parentCollection, localCollection);
                this.localCollection = (ConfigurationElementCollection) elementMerge.GetMergedElement();

                this.mergeableLocalElement = MergeableConfigurationCollectionFactory.GetCreateMergeableCollection(localCollection);

                //TODO : what to do around: localCollection.CollectionType
            }
            public ConfigurationElement GetMergedElement()
            {
                Dictionary<string, PropertyInformation> localProperties = localElement.ElementInformation.Properties.OfType<PropertyInformation>().ToDictionary(x => x.Name);
                Dictionary<string, PropertyInformation> parentProperties = parentElement.ElementInformation.Properties.OfType<PropertyInformation>().ToDictionary(x => x.Name);
                
                foreach (string propertyName in localProperties.Keys)
                {
                    PropertyInformation localProperty, parentProperty;
                    localProperty = localProperties[propertyName];
                    parentProperty = parentProperties[propertyName];

                    if (typeof(ConfigurationElement).IsAssignableFrom(localProperty.Type))
                    {
                        //either a collection or regular element

                        if (localProperty.Value == null)
                        {
                            localProperty.Value = parentProperty.Value;
                            continue;
                        }

                        if (parentProperty.Value != null)
                        {

                            if (typeof(ConfigurationElementCollection).IsAssignableFrom(localProperty.Type))
                            {
                                ConfigurationElementCollectionMerge merge = new ConfigurationElementCollectionMerge((ConfigurationElementCollection)parentProperty.Value, (ConfigurationElementCollection)localProperty.Value);
                                localProperty.Value = merge.GetMergedElementCollection();
                            }
                            else
                            {
                                ConfigurationElementMerge merge = new ConfigurationElementMerge((ConfigurationElement)parentProperty.Value, (ConfigurationElement)localProperty.Value);
                                localProperty.Value = merge.GetMergedElement();
                            }
                        }
                    }
                    else
                    {   
                        //just a regular property

                        if (ShouldOverrideLocalProperty(localProperty, parentProperty))
                        {
                            localProperty.Value = parentProperty.Value;
                        }
                    }
                }


                return localElement;
            }
            public ConfigurationSection GetMergedSection()
            {
                ConfigurationElementMerge elementMerge = new ConfigurationElementMerge(parentSection, localSection);

                return elementMerge.GetMergedElement() as ConfigurationSection;
            }