« SOA at the .NET Architecture Center | Main | Don Box on Transactions »

2004.07.08

Xml Serialization Handler

[editor's editor's note: I made another minor change. local-name() is a function, Jef. A function. That's what I get for not having a seamless publishing mechanism for my code straight from VS.NET.]

[editor's note: I made a minor mod to the code below after posting it, changing the xpath to ignore IncludeTypes if they weren't provided, rather than looking for the child configuration node by index]

Craig Andera blogged at one point about the last configuration section handler he would ever write. I had a similar idea, I googled, found his, liked it, used it. A couple of additional features were desirable to me, and so I modified it as follows:

// no warranties expressed or implied :)
using System;
using System.Configuration;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;
namespace Your.Namespace.Here
{
   public class XmlSerializerSectionHandler : IConfigurationSectionHandler
   {
    public XmlSerializerSectionHandler() {}
    public object Create( object parent, object configContext, System.Xml.XmlNode section)
    {
       string typename = section.Attributes["type"].Value;
       XmlNodeList list  = section.SelectNodes("./IncludedTypes/Type/text()");
       XmlNode configNode = section.SelectSingleNode("child::*[not(local-name() = 'IncludeTypes')]");
       Type[] types = new Type[list.Count];
       for(int i = 0; i < list.Count; i++)
       {
          types[i] = Type.GetType(list[i].Value, true);
       }
       Type t = Type.GetType ( typename );
      XmlSerializer ser = new XmlSerializer (
        t, 
        new XmlAttributeOverrides(), 
        types, 
        new XmlRootAttribute(configNode.LocalName), 
        null);
      return ser.Deserialize(new XmlNodeReader(configNode));
    }
  }
}

This version allows me to have a different name for the configuration object than the class name -
via new XmlRootAttribute(configNode.LocalName) - and allows me to provide custom types to support plug-in style functionality in the objects I am configuring. This lets me avoid the monstronsity that is XmlInclude (hate it hate it hate it hate it) while still having extensibility. I will try to provide a more detailed example shortly, but until then, here, at least, is a snippet of an example configuration xml:


<configuration>
<configSections>
<section name="SomeConfiguration" type="Your.Namespace.XmlSerializerSectionHandler, Your.Assembly"/>
</configSections>

<SomeConfiguration type='Your.Namespace.SomeConfiguration, Your.Assembly'>
<IncludedTypes>
<Type>Your.Namespace.ThisMessageSender, Your.Assembly</Type>
<Type>LandSafe.Messaging.ThatMessageReceiver, Your.Assembly</Type>
<Type></Type>
</IncludedTypes>
<NodeConfiguration
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
LogConfigurationFileName='Log.config'
ShareCounters='true'
InstanceName='Configuration Example'>
<Nodes>
<Node Verbose='false'>
<MessageHandler xsi:type='TransactionHandler'/>
<Receiver xsi:type='ThatMessageReceiver'>
<QueuePath>.\requests</QueuePath>
<MillisecondTimeout>30000</MillisecondTimeout>
</Receiver>
<Sender xsi:type='ThisMessageSender'>
<QueuePath>.\happy</QueuePath>
</Sender>
<ErrorSender xsi:type='ThisMessageSender'>
<QueuePath>.\errror</QueuePath>
</ErrorSender>
<ThreadCount>2</ThreadCount>
</Node>
</Nodes>
</NodeConfiguration>
</SomeConfiguration>
</configuration>

I hope that you can monkey around with it and infer proper use from that. A couple of nits -- Xml Serialization only supports abstract classes, it does not support interfaces. I do not try to take into account scoping classes to particular namespaces, or any such thing, though I am sure it isn't that difficult to get there. This hits the sweet spot for me.

(parenthetically speaking, (note the parentheses) Is it just me, or is DevelopMentor bleeding like a stuck pig? First the Don leaves. Then he steals many of the DM-meisters from the fold to work in the big house. Then I notice people like Aaron Skonnard going to Northface University (at least temporarily?), and Mike Woodring moving his .NET sample page back to his indiependent consulting site. Then I notice Barracuda while googling for a SharePoint 2004 implementation I was working on. Then Pluralsight kicks off, and dm folks move like fleas from a wet dog, Craig A. being the latest I have noticed. And not too long ago, the middleware co gave up on training and traded their courseware, etc to dm in exchange for content hosting. Related? Inquiring minds want to know.)

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83451806669e200d834566b0469e2

Listed below are links to weblogs that reference Xml Serialization Handler:

» Geek Notes 2004-07-14 from Geek Noise
[Read More]

Comments

I attended a course there not so long ago and got chatting to a guy attending the same course. They have had many great names leave and apparently the guy running the show there is "completely incompetent" and this has led to many of them wanting to get out. The course I attended was pretty good though.
Looks like I'm not the only one cribbing Craig's Serialization Handler. I recently wrote "The Very Last Configuration Section Handler I'll Ever Need" http://haacked.com/archive/2004/06/25/679.aspx But now I may have to revise it to include some of your stuff. :) Phil
Yeah, cool idea! It would be even better, if I could read the example code... ;-) Blue text on blue background isn't the best choice here.
Torsten -- I would apologize, but it is *my* blog, and blue is my favorite color!! No, really, I changed my styles in the typepad console, but apparently it took a while to flush the style changes out to all of the servers. Every misspelling [indiependent?] I slipped in seemed to arrive completely intact within mere seconds, though :)
I'm continually amazed by two things: 1) That this tiny bit of code I tossed off over a year ago is as popular as it is. :) 2) That people continue to find ways to make it cooler. In short, nice job - I like your changes!
I had only one problem with the last config section handler - Craig's original and this one too. It requires that you know the fully-qualified typename at config time. Me being *that* kind of person, I sometimes write quick-n-dirty ASPX pages that include the config type in the code-behind page. Now of course you know that the assembly is dynamically compiled and goofously named, and so there is no way to know the FQ assembly name at config time, to insert in the config file. Agk. Modifying the Create() method allows it to work. Given the just the namespace and Classname, 1. try to load the type from the currently executing assembly 2. try to load from the calling assembly (probably will not work in ASP.NET, in which the calling assembly is System.Web) 3. try loading from the page assembly (this will probably work). 4. try loading from assemblies referenced by the page /// nice. ///

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been saved. Comments are moderated and will not appear until approved by the author. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Comments are moderated, and will not appear until the author has approved them.

November 2008

Sun Mon Tue Wed Thu Fri Sat
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            
Blog powered by TypePad

We Like