1 //------------------------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------------------------ 4 5 namespace System.ServiceModel.Configuration 6 { 7 using System; 8 using System.Configuration; 9 10 [ConfigurationCollection(typeof(ExtensionElement), CollectionType = ConfigurationElementCollectionType.BasicMap)] 11 public class ExtensionElementCollection : ServiceModelConfigurationElementCollection<ExtensionElement> 12 { ExtensionElementCollection()13 public ExtensionElementCollection() 14 : base(ConfigurationElementCollectionType.BasicMap, ConfigurationStrings.Add) 15 { 16 } 17 BaseAdd(ConfigurationElement element)18 protected override void BaseAdd(ConfigurationElement element) 19 { 20 if (!this.InheritedElementExists((ExtensionElement)element)) 21 { 22 this.EnforceUniqueElement((ExtensionElement)element); 23 base.BaseAdd(element); 24 } 25 } 26 BaseAdd(int index, ConfigurationElement element)27 protected override void BaseAdd(int index, ConfigurationElement element) 28 { 29 if (!this.InheritedElementExists((ExtensionElement)element)) 30 { 31 this.EnforceUniqueElement((ExtensionElement)element); 32 base.BaseAdd(index, element); 33 } 34 } 35 GetElementKey(ConfigurationElement element)36 protected override object GetElementKey(ConfigurationElement element) 37 { 38 if (null == element) 39 { 40 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element"); 41 } 42 43 ExtensionElement configElementKey = (ExtensionElement)element; 44 return configElementKey.Name; 45 } 46 InheritedElementExists(ExtensionElement element)47 bool InheritedElementExists(ExtensionElement element) 48 { 49 // This is logic from ServiceModelEnhancedConfigurationElementCollection 50 // The idea is to allow duplicate identitcal extension definition in different level (i.e. app level and machine level) 51 // We however do not allow them on the same level. 52 // Identical extension is defined by same name and type. 53 object newElementKey = this.GetElementKey(element); 54 if (this.ContainsKey(newElementKey)) 55 { 56 ExtensionElement oldElement = (ExtensionElement)this.BaseGet(newElementKey); 57 if (null != oldElement) 58 { 59 // Is oldElement present in the different level of original config 60 // and name/type matching 61 if (!oldElement.ElementInformation.IsPresent && 62 element.Type.Equals(oldElement.Type, StringComparison.Ordinal)) 63 { 64 return true; 65 } 66 } 67 } 68 69 return false; 70 } 71 EnforceUniqueElement(ExtensionElement element)72 void EnforceUniqueElement(ExtensionElement element) 73 { 74 foreach (ExtensionElement extension in this) 75 { 76 if (element.Name.Equals(extension.Name, StringComparison.Ordinal)) 77 { 78 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException( 79 SR.GetString(SR.ConfigDuplicateExtensionName, element.Name))); 80 } 81 82 bool foundDuplicateType = false; 83 if (element.Type.Equals(extension.Type, StringComparison.OrdinalIgnoreCase)) 84 { 85 foundDuplicateType = true; 86 } 87 else if (element.TypeName.Equals(extension.TypeName, StringComparison.Ordinal)) 88 { 89 // In order to avoid extra assemblies being loaded, we perform type comparison only if the type names 90 // are the same. See bug CSDMain 222573. 91 Type elementType = Type.GetType(element.Type, false); 92 if (null != elementType && elementType.Equals(Type.GetType(extension.Type, false))) 93 { 94 foundDuplicateType = true; 95 } 96 } 97 98 if (foundDuplicateType) 99 { 100 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException( 101 SR.GetString(SR.ConfigDuplicateExtensionType, element.Type))); 102 } 103 } 104 } 105 106 protected override bool ThrowOnDuplicate 107 { 108 get 109 { 110 return true; 111 } 112 } 113 } 114 } 115