Sometimes in .NET programming, the general <appSettings> section of configuration is not enough to meet your needs. Fortunately, the .NET Framework provides a rich interface to create custom configuration sections for use in an application's configuration.
This is the second of several articles walking through a WCF Router for an enterprise WCTP service. The sections are:
Part 1 - Overview
Part 2 - Extending web.config
Part 3 - Defining the Service Contracts
Part 4 - Implementing the Router
Part 5 - An Asynchronous Service Implementation
Part 6 - A Synchronous Service Implementation
Part 7 - Advanced Services
In this section, we show how a custom configuration section is created to store settings for all of the services that our Router will send information to.
In the end, what we would like to have is a section in the XML configuration with something like the following:
<wctp> <receivers> <addReceiver name="Receiver1" intProperty="77" boolProperty="true" /> <addReceiver name="Receiver2" intProperty="114" boolProperty="false" > </receivers> </wctp>
This is done by using three custom classes which derive from base classes in the System.Configuration namespace. These are:
Let's look at these in detail.
The WctpConfig class is our class which is derived from ConfigurationSection, and represents the root XML element of our custom configuration. Since it only contains a single collection, the code if quite small:
[ConfigurationProperty("receivers", IsDefaultCollection = false)] [ConfigurationCollection(typeof(ReceiverCollection), AddItemName="addReceiver", ClearItemsName="clearReceivers", RemoveItemName="removeReceiver")] public ReceiverCollection Receivers { get { return (ReceiverCollection)(base["receivers"]); } }
Having the ability to use <clearReceivers> and <removeReceiver> elements allows use to machineToApplication settings, where some things could be defined in the machine.config file, or in other configuration files.
The ReceiverCollection class is the class derived from ConfigurationElementCollection. It contains methods to get elements in the collection via integral index or string key, and also to add, remove, and clear the child elements.
This class is fairly generic and with minor modifications could easily be used in other projects.
This is the class derived from ConfigurationElement. It contains the really custom code for our configuration tree. So let's look at what this is going to do for us.
In this class, we will have the information necessary to decide which possible Receiver to route WCTP messages to. So we would like it to have some very specific information:
Implementing these is fairly straightforward. Here is an example of the HandlesText property.
////// Whether or not the service supports text messages. True by default. /// [ConfigurationProperty("text", IsRequired = false, DefaultValue = true)] public bool HandlesText { get { return (bool)this["text"]; } set { this["text"] = value; } }
Skipping ahead a bit to the implementation of the WCTP HTTP Application, making use of the configuration is very easy. When deciding which WCF service to route a particular mesage to, a simple LINQ query can be executed to return an ordered list of prioritized potential services.
//Create a LINQ query to get the order of services to send the message to WctpConfig config = (WctpConfig)(ConfigurationManager.GetSection("WCTP")); IEnumerable<WctpConfig>receivers; if (payload.GetType() == typeof(string)) { receivers = config.Receivers.OfType () .Where(s => s.HandlesText) .Where(s => Regex.Match(originator.senderID, s.SenderFilter).Success) .Where(s => Regex.Match(recipient.recipientID, s.RecipientFilter).Success) .OrderByDescending(s => s.Priority) .ThenByDescending(s => s.ExclusiveHandler) .ThenByDescending(s => s.OneWay); } else { receivers = config.Receivers.OfType () .Where(s => s.HandlesBinary) .Where(s => Regex.Match(originator.senderID, s.SenderFilter).Success) .Where(s => Regex.Match(recipient.recipientID, s.RecipientFilter).Success) .OrderByDescending(s => s.Priority) .ThenByDescending(s => s.ExclusiveHandler) .ThenByDescending(s => s.OneWay); }
Isn't that nice!
I find myself in awe more and more over the functionality contained within LINQ.
Mar 13, 2008 - Original Document
| You must Sign In to use this message board. | ||||||||||||||
|
||||||||||||||
|
||||||||||||||