Monday, March 9, 2009

Castle: We Still XML The Old Way

Post 4 in a 101 series on the Castle IOC project called Windsor. See part one for background

XML Config Based Registration

Although demoware may show us the inline registration of components is good it may not prove to be the best thing for your application. The previous posts have shown registration of types in C#, this means we must recompile if we are making changes to any parts of our registration. This may be considered a bad thing, it may also be considered a bad thing that the assembly that you are performing all of this registration in knows about (and has references to)  a lot of possibly inappropriate libraries and projects. One way around all of this is by using the XML configuration.

Using our same basic console app I add an app.config file and put the following in it:

<?xml version="1.0" encoding="utf-8" ?>
<section name="castle"
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
<component lifestyle="transient"
service="CastleIocConsole.IWriter, CastleIocConsole"
type="CastleIocConsole.HelloWriter, CastleIocConsole" />
service="CastleIocConsole.IWriter, CastleIocConsole"
type="CastleIocConsole.GdayWriter, CastleIocConsole" />
service="CastleIocConsole.IWriter, CastleIocConsole"
type="CastleIocConsole.ListWriter, CastleIocConsole" />
service="CastleIocConsole.IMessageService, CastleIocConsole"
type="CastleIocConsole.GuidMessageService, CastleIocConsole" />

Several things to note:

  • You should specify the fully qualified name any time you are declaring types in XML, that is - Full.NameSpace.Type, Assembly

  • All components have an id

  • You don't need to specify a service, if the type has no interface or is the base calls you can just declare the type.

  • you can declare lifestyles (the transient lifestyle specified is not important in this example, its just there to show it can be done)

In addition to this you can specify which concrete dependencies you want, assign component properties and declare interceptors for AOP style run time inject of code blocks (more on this to come)

Using this code we could do some thing like this:

using System;
using Castle.Core.Resource;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;

namespace CastleIocConsole
class Program
static void Main(string[] args)
IWindsorContainer container =
new WindsorContainer(
new XmlInterpreter(
new ConfigResource("castle")));
var writer1 = container.Resolve<IWriter>();
var writer2 = container.Resolve<IWriter>("List");

which would give the output of (see previous post for component definitions):

Hello World

As with any XML there seems to be a few catches so here are some gotchas that may help:

  • All components need an ID

  • First in best dressed: The first component registered is the default for that service (interface)

  • Standard .net XML config notation applies eg no line breaks in definitions, generics marked up with back tick notation etc

  • There is no official XSD schema but there are user defined ones, find one and put it is  the VS schema folder eg : C:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas to give you intellisense

That is the last in the 101 series for now. Soon I would like to cover

  • Interception and how you can use AOP with the Castle framework

  • Run time Config with out XML (Binsor)


Back to Post 3

No comments: