Correct implementation of a custom config section with nested collections?
In a web application, I want to be able to define some mapping using a config section like this:
<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>
I'm struggling to achieve this goal, especially when defining my collection of collections. What are the classes that I need to implement to achieve this?
Currently, I have:
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"];
}
}
}
But, this is not working as expected.
I finally found this guy's example. It was coded and worked right out of the box.
http://manyrootsofallevilrants.blogspot.com/2011/07/nested-custom-configuration-collections.html
I am going to paste the code here......only because I cannot stand it when someone says "Your answer is here", and the link is dead.
Please try his website first, and leave a "thank you" if it works.
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; } } } }
And the configuration code
<?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>
And then the "call"
TunnelSection tunnels = ConfigurationManager.GetSection("TunnelSection") as TunnelSection
Due to the popularity of my other answer, I've written a custom example using Usa-States and Usa-Counties. An example that's a tad easier to follow.
I've also added some interfaces, which allows some mocking for unit-tests, something I wasn't fully aware of when I wrote this original answer.
I also added putting the settings in its own file, so your app.config file doesn't have a billion things in it.
I've also added a "Finder" to encapsulate searching for a specific item in the collection.
I've also added a custom Enum.
"UsaStatesSettings.config" (make sure you mark this as "copy-always")
<?xml version="1.0" encoding="utf-8" ?>
<UsaStateDefinitionConfigurationSectionName>
<usaStateDefinition usaStateFullName="Virginia" usaStateAbbreviation="VA" countyLabelName="County" usaStateDefinitionUniqueIdentifier="111" isContenential="true" >
<usaCounties>
<usaCounty usaCountyValue="Bath" />
<usaCounty usaCountyValue="Bedford" />
<usaCounty usaCountyValue="Bland" />
</usaCounties>
</usaStateDefinition>
<!-- -->
<usaStateDefinition usaStateFullName="North Carolina" usaStateAbbreviation="NC" countyLabelName="County" usaStateDefinitionUniqueIdentifier="222" isContenential="true" >
<usaCounties>
<usaCounty usaCountyValue="Catawba" />
<usaCounty usaCountyValue="Chatham" />
<usaCounty usaCountyValue="Chowan" />
</usaCounties>
</usaStateDefinition>
<!-- -->
<usaStateDefinition usaStateFullName="Alaska" usaStateAbbreviation="AK" countyLabelName="Borough" usaStateDefinitionUniqueIdentifier="333" isContenential="false" >
<usaCounties>
<usaCounty usaCountyValue="Aleutians East" />
</usaCounties>
</usaStateDefinition>
<!-- -->
<usaStateDefinition usaStateFullName="Lousiania" usaStateAbbreviation="LA" countyLabelName="Parish" usaStateDefinitionUniqueIdentifier="444" isContenential="true" >
<usaCounties>
<usaCounty usaCountyValue="Acadia" />
</usaCounties>
</usaStateDefinition>
</UsaStateDefinitionConfigurationSectionName>
The "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>
and now the "code"
/**/
// 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;
}
}
}
精彩评论