使用嵌套集合正确实现自定义configuration节?

在一个Web应用程序中,我希望能够使用像这样的configuration部分定义一些映射:

<configuration> <configSections> <sectionGroup name="MyCustomer"> <section name="CatalogMappings" type="MyCustom.MyConfigSection" /> </sectionGroup> </configSections> <MyCustomer> <catalogMappings> <catalog name="toto"> <mapping value="1" displayText="titi" /> <mapping value="2" displayText="tata" /> </catalog> <catalog name="toto2"> <mapping value="1" displayText="titi2" /> <mapping value="2" displayText="tata2" /> </catalog> </catalogMappings> </MyCustomer> </configuration> 

我正在努力实现这一目标,特别是在定义我的collections集时。 我需要实现什么类来实现这个目标?

目前,我有:

 public class CatalogMappingSection : System.Configuration.ConfigurationSection { public class Mapping : ConfigurationElement { [ConfigurationProperty("externalKey")] public string ExternalKey { get; set; } [ConfigurationProperty("displayText", IsRequired=true)] public string DisplayText { get; set; } [ConfigurationProperty("value", IsRequired=true, IsKey=true)] public int Value { get; set; } } public class Catalog : ConfigurationElementCollection { [ConfigurationProperty("name", IsRequired=true, IsKey=true)] public string Name { get; set; } protected override ConfigurationElement CreateNewElement() { return new Mapping(); } protected override object GetElementKey(ConfigurationElement element) { return ((Mapping)element).Value; } } public class CatalogCollection : ConfigurationElementCollection { [ConfigurationProperty("catalog")] [ConfigurationCollection(typeof(Catalog))] public Catalog CatalogMappingCollection { get { return (Catalog)base["catalog"]; } } protected override ConfigurationElement CreateNewElement() { return new Catalog(); } protected override object GetElementKey(ConfigurationElement element) { return ((Catalog)element).Name; } } [ConfigurationProperty("catalogMappings")] [ConfigurationCollection(typeof(CatalogCollection))] public CatalogCollection CatalogMappings { get { return (CatalogCollection)base["catalogMappings"]; } } } 

但是,这并不像预期的那样工作。

我终于find了这个人的例子。 它被编码,并开箱即用。

http://manyrootsofallevilrants.blogspot.com/2011/07/nested-custom-configuration-collections.html

我要在这里粘贴代码……只是因为当别人说“你的答案在这里”,而且链接已经死了,我无法忍受。

请先尝试他的网站,如果有效,请留下“谢谢”。

 using System; using System.Configuration; namespace SSHTunnelWF { public class TunnelSection : ConfigurationSection { [ConfigurationProperty("", IsDefaultCollection = true)] public HostCollection Tunnels { get { HostCollection hostCollection = (HostCollection)base[""]; return hostCollection; } } } public class HostCollection : ConfigurationElementCollection { public HostCollection() { HostConfigElement details = (HostConfigElement)CreateNewElement(); if (details.SSHServerHostname != "") { Add(details); } } public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } protected override ConfigurationElement CreateNewElement() { return new HostConfigElement(); } protected override Object GetElementKey(ConfigurationElement element) { return ((HostConfigElement)element).SSHServerHostname; } public HostConfigElement this[int index] { get { return (HostConfigElement)BaseGet(index); } set { if (BaseGet(index) != null) { BaseRemoveAt(index); } BaseAdd(index, value); } } new public HostConfigElement this[string name] { get { return (HostConfigElement)BaseGet(name); } } public int IndexOf(HostConfigElement details) { return BaseIndexOf(details); } public void Add(HostConfigElement details) { BaseAdd(details); } protected override void BaseAdd(ConfigurationElement element) { BaseAdd(element, false); } public void Remove(HostConfigElement details) { if (BaseIndexOf(details) >= 0) BaseRemove(details.SSHServerHostname); } public void RemoveAt(int index) { BaseRemoveAt(index); } public void Remove(string name) { BaseRemove(name); } public void Clear() { BaseClear(); } protected override string ElementName { get { return "host"; } } } public class HostConfigElement:ConfigurationElement { [ConfigurationProperty("SSHServerHostname", IsRequired = true, IsKey = true)] [StringValidator(InvalidCharacters = " ~!@#$%^&*()[]{}/;'\"|\\")] public string SSHServerHostname { get { return (string)this["SSHServerHostname"]; } set { this["SSHServerHostname"] = value; } } [ConfigurationProperty("username", IsRequired = true)] [StringValidator(InvalidCharacters = " ~!@#$%^&*()[]{}/;'\"|\\")] public string Username { get { return (string)this["username"]; } set { this["username"] = value; } } [ConfigurationProperty("SSHport", IsRequired = true, DefaultValue = 22)] [IntegerValidator(MinValue = 1, MaxValue = 65536)] public int SSHPort { get { return (int)this["SSHport"]; } set { this["SSHport"] = value; } } [ConfigurationProperty("password", IsRequired = false)] public string Password { get { return (string)this["password"]; } set { this["password"] = value; } } [ConfigurationProperty("privatekey", IsRequired = false)] public string Privatekey { get { return (string)this["privatekey"]; } set { this["privatekey"] = value; } } [ConfigurationProperty("privatekeypassphrase", IsRequired = false)] public string Privatekeypassphrase { get { return (string)this["privatekeypassphrase"]; } set { this["privatekeypassphrase"] = value; } } [ConfigurationProperty("tunnels", IsDefaultCollection = false)] public TunnelCollection Tunnels { get { return (TunnelCollection)base["tunnels"]; } } } public class TunnelCollection : ConfigurationElementCollection { public new TunnelConfigElement this[string name] { get { if (IndexOf(name) < 0) return null; return (TunnelConfigElement)BaseGet(name); } } public TunnelConfigElement this[int index] { get { return (TunnelConfigElement)BaseGet(index); } } public int IndexOf(string name) { name = name.ToLower(); for (int idx = 0; idx < base.Count; idx++) { if (this[idx].Name.ToLower() == name) return idx; } return -1; } public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } protected override ConfigurationElement CreateNewElement() { return new TunnelConfigElement(); } protected override object GetElementKey(ConfigurationElement element) { return ((TunnelConfigElement)element).Name; } protected override string ElementName { get { return "tunnel"; } } } public class TunnelConfigElement : ConfigurationElement { public TunnelConfigElement() { } public TunnelConfigElement(string name, int localport, int remoteport, string destinationserver) { this.DestinationServer = destinationserver; this.RemotePort = remoteport; this.LocalPort = localport; this.Name = name; } [ConfigurationProperty("name", IsRequired = true, IsKey = true, DefaultValue = "")] public string Name { get { return (string)this["name"]; } set { this["name"] = value; } } [ConfigurationProperty("localport", IsRequired = true, DefaultValue =1)] [IntegerValidator(MinValue = 1, MaxValue = 65536)] public int LocalPort { get { return (int)this["localport"]; } set { this["localport"] = value; } } [ConfigurationProperty("remoteport", IsRequired = true, DefaultValue =1)] [IntegerValidator(MinValue = 1, MaxValue = 65536)] public int RemotePort { get { return (int)this["remoteport"]; } set { this["remoteport"] = value; } } [ConfigurationProperty("destinationserver", IsRequired = true)] [StringValidator(InvalidCharacters = " ~!@#$%^&*()[]{}/;'\"|\\")] public string DestinationServer { get { return (string)this["destinationserver"]; } set { this["destinationserver"] = value; } } } } 

和configuration代码

  <?xml version="1.0"?> <configuration> <configSections> <section name="TunnelSection" type="SSHTunnelWF.TunnelSection,SSHTunnelWF" /> </configSections> <TunnelSection> <host SSHServerHostname="tsg.edssdn.net" username="user" SSHport="22" password="pass" privatekey="" privatekeypassphrase=""> <tunnels> <tunnel name="tfs" localport="8081" remoteport="8080" destinationserver="tfs2010.dev.com" /> <tunnel name="sql" localport="14331" remoteport="1433" destinationserver="sql2008.dev.com" /> <tunnel name="crm2011app" localport="81" remoteport="80" destinationserver="crm2011betaapp.dev.com" /> </tunnels> </host> <host SSHServerHostname="blade16" username="root" SSHport="22" password="pass" privatekey="" privatekeypassphrase=""> <tunnels> <tunnel name="vnc" localport="5902" remoteport="5902" destinationserver="blade1.dev.com" /> </tunnels> </host> </TunnelSection> </configuration> 

然后“打电话”

 TunnelSection tunnels = ConfigurationManager.GetSection("TunnelSection") as TunnelSection 

由于我的其他答案的普及,我写了一个定制的例子,使用美国国家和美国郡。 一个比较容易遵循的例子。

我还添加了一些接口,它允许一些模拟unit testing,我没有完全意识到,当我写这个原始的答案。

我还添加了设置在自己的文件,所以你的app.config文件中没有十亿个东西。

我还添加了一个“Finder”封装search集合中的特定项目。

我也添加了一个自定义枚举。

“UsaStatesSettings.config”(确保将其标记为“始终复制”)

 <?xml version="1.0" encoding="utf-8" ?> <UsaStateDefinitionConfigurationSectionName> <usaStateDefinition usaStateFullName="Virginia" usaStateAbbreviation="VA" countyLabelName="County" usaStateDefinitionUniqueIdentifier="111" isContenential="true" > <usaCounties> <usaCounty usaCountyValue="Frederick" /> <usaCounty usaCountyValue="Shenandoah" /> <usaCounty usaCountyValue="Loudon" /> </usaCounties> </usaStateDefinition> <!-- --> <usaStateDefinition usaStateFullName="NorthCarolina" usaStateAbbreviation="NC" countyLabelName="County" usaStateDefinitionUniqueIdentifier="222" isContenential="true" > <usaCounties> <usaCounty usaCountyValue="Wake" /> <usaCounty usaCountyValue="Chatham" /> </usaCounties> </usaStateDefinition> <!-- --> <usaStateDefinition usaStateFullName="Alaska" usaStateAbbreviation="AK" countyLabelName="Borough" usaStateDefinitionUniqueIdentifier="333" isContenential="false" > <usaCounties> <usaCounty usaCountyValue="Aleutians East Borough" /> </usaCounties> </usaStateDefinition> <!-- --> <usaStateDefinition usaStateFullName="Lousiania" usaStateAbbreviation="LA" countyLabelName="Parish" usaStateDefinitionUniqueIdentifier="444" isContenential="true" > <usaCounties> <usaCounty usaCountyValue="Acadia Parish" /> </usaCounties> </usaStateDefinition> </UsaStateDefinitionConfigurationSectionName> 

“app.config”

 <?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="UsaStateDefinitionConfigurationSectionName" type="GranadaCoder.CustomConfigurationExample.Configuration.UsaStateDefinitionConfigurationSection,GranadaCoder.CustomConfigurationExample.Configuration" /> </configSections> <UsaStateDefinitionConfigurationSectionName configSource="UsaStatesSettings.config" /> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> </configuration> 

现在的“代码”

 /**/ // file="CaseInsensitiveEnumConfigurationValueConverter.cs" using System; using System.ComponentModel; using System.Configuration; using System.Globalization; namespace GranadaCoder.CustomConfigurationExample.Configuration { public class CaseInsensitiveEnumConfigurationValueConverter<T> : ConfigurationConverterBase { public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data) { return Enum.Parse(typeof(T), (string)data, true); } } } /**/ // file="UsaCountyCollection.cs" using System.Collections.Generic; using System.Configuration; namespace GranadaCoder.CustomConfigurationExample.Configuration { [ConfigurationCollection(typeof(UsaCountyConfigurationElement))] public class UsaCountyCollection : ConfigurationElementCollection, IEnumerable<UsaCountyConfigurationElement> { public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } protected override string ElementName { get { return "usaCounty"; } } public UsaCountyConfigurationElement this[int index] { get { return (UsaCountyConfigurationElement)BaseGet(index); } } public new UsaCountyConfigurationElement this[string name] { get { if (this.IndexOf(name) < 0) { return null; } return (UsaCountyConfigurationElement)BaseGet(name); } } public void Add(UsaCountyConfigurationElement newItem) { this.BaseAdd(newItem); } public int IndexOf(string usaCountyValue) { for (int idx = 0; idx < this.Count; idx++) { if (this[idx].UsaCountyValue.ToLower(System.Globalization.CultureInfo.CurrentCulture) == usaCountyValue.ToLower(System.Globalization.CultureInfo.CurrentCulture)) { return idx; } } return -1; } public new IEnumerator<UsaCountyConfigurationElement> GetEnumerator() { int count = this.Count; for (int i = 0; i < count; i++) { yield return this.BaseGet(i) as UsaCountyConfigurationElement; } } protected override ConfigurationElement CreateNewElement() { return new UsaCountyConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { return ((UsaCountyConfigurationElement)element).UsaCountyValue; } } } /**/ // file="UsaCountyConfigurationElement.cs" using System.ComponentModel; using System.Configuration; namespace GranadaCoder.CustomConfigurationExample.Configuration { [System.Diagnostics.DebuggerDisplay("UsaCountyValue='{UsaCountyValue}'")] public class UsaCountyConfigurationElement : ConfigurationElement { private const string UsaCountyValuePropertyName = "usaCountyValue"; public UsaCountyConfigurationElement() { } public UsaCountyConfigurationElement(string usaCountyValue) { this.UsaCountyValue = usaCountyValue; } [ConfigurationProperty(UsaCountyValuePropertyName, IsRequired = true, IsKey = true, DefaultValue = "")] [StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;'\"|\\")] public string UsaCountyValue { get { return (string)this[UsaCountyValuePropertyName]; } set { this[UsaCountyValuePropertyName] = value; } } } } /**/ // file="UsaCountyLabelEnum.cs" namespace GranadaCoder.CustomConfigurationExample.Configuration { public enum UsaCountyLabelEnum { Unknown, County, Parish, Borough } } /**/ // file="UsaStateDefinitionCollection.cs" using System; using System.Collections.Generic; using System.Configuration; using GranadaCoder.CustomConfigurationExample.Configuration.Interfaces; namespace GranadaCoder.CustomConfigurationExample.Configuration { [ConfigurationCollection(typeof(UsaStateDefinitionConfigurationElement))] public class UsaStateDefinitionCollection : ConfigurationElementCollection, IUsaStateDefinitionCollection { public UsaStateDefinitionCollection() { UsaStateDefinitionConfigurationElement details = (UsaStateDefinitionConfigurationElement)this.CreateNewElement(); if (!string.IsNullOrEmpty(details.UsaStateFullName)) { this.Add(details); } } public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } bool ICollection<UsaStateDefinitionConfigurationElement>.IsReadOnly { get { return false; } } protected override string ElementName { get { return "usaStateDefinition"; } } public UsaStateDefinitionConfigurationElement this[int index] { get { return (UsaStateDefinitionConfigurationElement)BaseGet(index); } set { if (this.BaseGet(index) != null) { this.BaseRemoveAt(index); } this.BaseAdd(index, value); } } public new UsaStateDefinitionConfigurationElement this[string name] { get { return (UsaStateDefinitionConfigurationElement)this.BaseGet(name); } } public int IndexOf(UsaStateDefinitionConfigurationElement details) { return this.BaseIndexOf(details); } public void Add(UsaStateDefinitionConfigurationElement newItem) { this.BaseAdd(newItem); } public bool Remove(UsaStateDefinitionConfigurationElement details) { if (this.BaseIndexOf(details) >= 0) { this.BaseRemove(details.UsaStateFullName); return true; } return false; } public void RemoveAt(int index) { this.BaseRemoveAt(index); } public void Remove(string name) { this.BaseRemove(name); } public void Clear() { this.BaseClear(); } public bool Contains(UsaStateDefinitionConfigurationElement item) { if (this.IndexOf(item) >= 0) { return true; } return false; } public void CopyTo(UsaStateDefinitionConfigurationElement[] array, int arrayIndex) { throw new NotImplementedException(); } public void Insert(int index, UsaStateDefinitionConfigurationElement item) { this.BaseAdd(index, item); } public new IEnumerator<UsaStateDefinitionConfigurationElement> GetEnumerator() { int count = this.Count; for (int i = 0; i < count; i++) { yield return this.BaseGet(i) as UsaStateDefinitionConfigurationElement; } } protected override ConfigurationElement CreateNewElement() { return new UsaStateDefinitionConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { return ((UsaStateDefinitionConfigurationElement)element).UsaStateFullName; } protected override void BaseAdd(ConfigurationElement element) { this.BaseAdd(element, false); } } } /**/ // file="UsaStateDefinitionConfigurationElement.cs" using System; using System.ComponentModel; using System.Configuration; namespace GranadaCoder.CustomConfigurationExample.Configuration { [System.Diagnostics.DebuggerDisplay("UsaStateFullName = '{UsaStateFullName}'")] public class UsaStateDefinitionConfigurationElement : ConfigurationElement { private const string UsaStateFullNamePropertyName = "usaStateFullName"; private const string UsaStateAbbreviationPropertyName = "usaStateAbbreviation"; private const string UsaStateDefinitionUniqueIdentifierPropertyName = "usaStateDefinitionUniqueIdentifier"; private const string IsContenentialPropertyName = "isContenential"; private const string CountyLabelNamePropertyName = "countyLabelName"; private const string UsaCountiesPropertyName = "usaCounties"; private const string ServiceBusQueuesPropertyName = "serviceBusQueues"; [ConfigurationProperty(UsaStateFullNamePropertyName, IsRequired = true, IsKey = true)] [StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;'\"|\\")] public string UsaStateFullName { get { return (string)this[UsaStateFullNamePropertyName]; } set { this[UsaStateFullNamePropertyName] = value; } } [ConfigurationProperty(UsaStateAbbreviationPropertyName, IsRequired = true, IsKey = true)] [StringValidator(InvalidCharacters = " ~!@#$%^&*()[]{}/;'\"|\\")] public string UsaStateAbbreviation { get { return (string)this[UsaStateAbbreviationPropertyName]; } set { this[UsaStateAbbreviationPropertyName] = value; } } [ConfigurationProperty(UsaStateDefinitionUniqueIdentifierPropertyName, IsRequired = true)] public int UsaStateDefinitionUniqueIdentifier { get { return (int)this[UsaStateDefinitionUniqueIdentifierPropertyName]; } set { this[UsaStateDefinitionUniqueIdentifierPropertyName] = value; } } [ConfigurationProperty(IsContenentialPropertyName, IsRequired = true)] public bool IsContenential { get { return (bool)this[IsContenentialPropertyName]; } set { this[IsContenentialPropertyName] = value; } } [ConfigurationProperty(UsaCountiesPropertyName, IsDefaultCollection = false)] public UsaCountyCollection UsaCounties { get { return (UsaCountyCollection)base[UsaCountiesPropertyName]; } set { this[UsaCountiesPropertyName] = value; } /* set is here for UnitTests */ } [ConfigurationProperty(CountyLabelNamePropertyName, DefaultValue = UsaCountyLabelEnum.Unknown)] [TypeConverter(typeof(CaseInsensitiveEnumConfigurationValueConverter<UsaCountyLabelEnum>))] public UsaCountyLabelEnum CountyLabelType { get { return (UsaCountyLabelEnum)this[CountyLabelNamePropertyName]; } set { base[CountyLabelNamePropertyName] = value; } } } } /**/ // file="UsaStateDefinitionConfigurationRetriever.cs" using System; using System.Configuration; using System.Linq; using GranadaCoder.CustomConfigurationExample.Configuration.Interfaces; namespace GranadaCoder.CustomConfigurationExample.Configuration { public class UsaStateDefinitionConfigurationRetriever : IUsaStateDefinitionConfigurationSectionRetriever { public static readonly string ConfigurationSectionName = "UsaStateDefinitionConfigurationSectionName"; public IUsaStateDefinitionConfigurationSection GetIUsaStateDefinitionConfigurationSection() { UsaStateDefinitionConfigurationSection returnSection = (UsaStateDefinitionConfigurationSection)ConfigurationManager.GetSection(ConfigurationSectionName); if (returnSection != null) { var duplicates = returnSection.IUsaStateDefinitions.GroupBy(i => new { i.UsaStateDefinitionUniqueIdentifier }) .Where(g => g.Count() > 1) .Select(g => g.Key); if (duplicates.Count() > 1) { throw new ArgumentOutOfRangeException("Duplicate UsaStateDefinitionUniqueIdentifier values.", Convert.ToString(duplicates.First().UsaStateDefinitionUniqueIdentifier)); } return returnSection; } return null; } } } /**/ // file="UsaStateDefinitionConfigurationSection.cs" using System.Configuration; using GranadaCoder.CustomConfigurationExample.Configuration.Interfaces; namespace GranadaCoder.CustomConfigurationExample.Configuration { public class UsaStateDefinitionConfigurationSection : ConfigurationSection, IUsaStateDefinitionConfigurationSection { [ConfigurationProperty("", IsDefaultCollection = true)] public UsaStateDefinitionCollection UsaStateDefinitions { get { UsaStateDefinitionCollection coll = (UsaStateDefinitionCollection)base[string.Empty]; return coll; } } /* Here is the interface property that simply returns the non-interface property from above. This allows System.Configuration to hydrate the non-interface property, but allows the code to be written (and unit test mocks to be written) against the interface property. */ public IUsaStateDefinitionCollection IUsaStateDefinitions { get { return this.UsaStateDefinitions; } } } } /**/ // file="UsaStateDefinitionFinder.cs" using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using GranadaCoder.CustomConfigurationExample.Configuration.Interfaces; namespace GranadaCoder.CustomConfigurationExample.Configuration { public class UsaStateDefinitionFinder : IUsaStateDefinitionFinder { private const string ErrorMessageMoreThanOneMatch = "More than item was found with the selection criteria. ({0})"; private const string ErrorMessageNoMatch = "No item was found with the selection criteria. ({0})"; public UsaStateDefinitionConfigurationElement FindUsaStateDefinitionConfigurationElement(IUsaStateDefinitionConfigurationSection settings, string usaStateFullName) { UsaStateDefinitionConfigurationElement returnItem = null; if (null != settings && null != settings.IUsaStateDefinitions) { ICollection<UsaStateDefinitionConfigurationElement> matchingFarmItems; matchingFarmItems = settings.IUsaStateDefinitions.Where(ele => usaStateFullName.Equals(ele.UsaStateFullName, StringComparison.OrdinalIgnoreCase)).ToList(); if (matchingFarmItems.Count > 1) { string errorDetails = this.BuildErrorDetails(matchingFarmItems); throw new IndexOutOfRangeException(string.Format(ErrorMessageMoreThanOneMatch, errorDetails)); } returnItem = matchingFarmItems.FirstOrDefault(); } return returnItem; } public UsaStateDefinitionConfigurationElement FindUsaStateDefinitionConfigurationElement(string usaStateFullName) { IUsaStateDefinitionConfigurationSection settings = new UsaStateDefinitionConfigurationRetriever().GetIUsaStateDefinitionConfigurationSection(); return this.FindUsaStateDefinitionConfigurationElement(settings, usaStateFullName); } public UsaStateDefinitionConfigurationElement FindUsaStateDefinitionConfigurationElementByUniqueId(int id) { IUsaStateDefinitionConfigurationSection settings = new UsaStateDefinitionConfigurationRetriever().GetIUsaStateDefinitionConfigurationSection(); return this.FindUsaStateDefinitionConfigurationElementByUniqueId(settings, id); } public UsaStateDefinitionConfigurationElement FindUsaStateDefinitionConfigurationElementByUniqueId(IUsaStateDefinitionConfigurationSection settings, int id) { UsaStateDefinitionConfigurationElement returnItem = null; if (null != settings && null != settings.IUsaStateDefinitions) { ICollection<UsaStateDefinitionConfigurationElement> matchingFarmItems; matchingFarmItems = settings.IUsaStateDefinitions.Where(ele => id == ele.UsaStateDefinitionUniqueIdentifier).ToList(); if (matchingFarmItems.Count > 1) { string errorDetails = this.BuildErrorDetails(matchingFarmItems); throw new IndexOutOfRangeException(string.Format(ErrorMessageMoreThanOneMatch, errorDetails)); } returnItem = matchingFarmItems.FirstOrDefault(); } return returnItem; } private string BuildErrorDetails(ICollection<UsaStateDefinitionConfigurationElement> items) { string returnValue; StringBuilder sb = new StringBuilder(); if (null != items) { foreach (UsaStateDefinitionConfigurationElement item in items) { sb.Append(string.Format("UsaStateFullName='{0}'.", item.UsaStateFullName)); } } returnValue = sb.ToString(); return returnValue; } } } /**/ // file="IUsaStateDefinitionCollection.cs" using System; using System.Collections.Generic; namespace GranadaCoder.CustomConfigurationExample.Configuration.Interfaces { public interface IUsaStateDefinitionCollection : IList<UsaStateDefinitionConfigurationElement>, IEnumerable<UsaStateDefinitionConfigurationElement> /* Implement IEnumerable to allow Linq queries */ { UsaStateDefinitionConfigurationElement this[string name] { get; } void Remove(string name); } } /**/ // file="IUsaStateDefinitionConfigurationSection.cs" using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace GranadaCoder.CustomConfigurationExample.Configuration.Interfaces { public interface IUsaStateDefinitionConfigurationSection { IUsaStateDefinitionCollection IUsaStateDefinitions { get; } } } /**/ // file="IUsaStateDefinitionConfigurationSectionRetriever.cs" namespace GranadaCoder.CustomConfigurationExample.Configuration.Interfaces { public interface IUsaStateDefinitionConfigurationSectionRetriever { IUsaStateDefinitionConfigurationSection GetIUsaStateDefinitionConfigurationSection(); } } /**/ // file="IUsaStateDefinitionFinder.cs" using System; namespace GranadaCoder.CustomConfigurationExample.Configuration.Interfaces { public interface IUsaStateDefinitionFinder { UsaStateDefinitionConfigurationElement FindUsaStateDefinitionConfigurationElement(IUsaStateDefinitionConfigurationSection settings, string usaStateFullName); UsaStateDefinitionConfigurationElement FindUsaStateDefinitionConfigurationElement(string usaStateFullName); UsaStateDefinitionConfigurationElement FindUsaStateDefinitionConfigurationElementByUniqueId(int id); UsaStateDefinitionConfigurationElement FindUsaStateDefinitionConfigurationElementByUniqueId(IUsaStateDefinitionConfigurationSection settings, int id); } } /**/ // file="Program.cs" using System; using System.Text; using GranadaCoder.CustomConfigurationExample.Configuration; using GranadaCoder.CustomConfigurationExample.Configuration.Interfaces; using log4net; using Microsoft.Practices.Unity; namespace GranadaCoder.CustomConfigurationExample.ConsoleAppOne { public static class Program { public const int UnhandledExceptionErrorCode = 1; private static readonly ILog TheLogger = LogManager.GetLogger(typeof(Program)); public static int Main(string[] args) { int returnValue = 0; string logMsg = string.Empty; try { //// For future //log4net.Config.XmlConfigurator.Configure(); //// For future //IUnityContainer container = new UnityContainer(); //// For future //container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(GranadaCoder.CustomConfigurationExample.ConsoleAppOne.Program)))); IUsaStateDefinitionConfigurationSectionRetriever retr = new UsaStateDefinitionConfigurationRetriever(); IUsaStateDefinitionConfigurationSection section = retr.GetIUsaStateDefinitionConfigurationSection(); IUsaStateDefinitionFinder finder = new UsaStateDefinitionFinder(); UsaStateDefinitionConfigurationElement foundElement = finder.FindUsaStateDefinitionConfigurationElement("Virginia"); if (null != section) { foreach (UsaStateDefinitionConfigurationElement state in section.IUsaStateDefinitions) { Console.WriteLine("state.UsaStateFullName='{0}', state.UsaStateAbbreviation='{1}', state.IsContenential='{2}', state.CountyLabelType='{3}'", state.UsaStateFullName, state.UsaStateAbbreviation, state.IsContenential, state.CountyLabelType); foreach (UsaCountyConfigurationElement county in state.UsaCounties) { Console.WriteLine("county.UsaCountyValue='{0}'", county.UsaCountyValue); } Console.WriteLine("--------------------"); } } } catch (Exception e) { TheLogger.Error(e.Message, e); Console.WriteLine("Unexpected Exception : {0}", e.Message); returnValue = UnhandledExceptionErrorCode; } Console.WriteLine("END : {0}", System.Diagnostics.Process.GetCurrentProcess().ProcessName); Console.WriteLine(string.Empty); Console.WriteLine("Press ENTER to exit"); Console.ReadLine(); return returnValue; } } }