# Saturday, September 06, 2008
As a brief follow up to my last post here I thought I'd quickly post about something I've been doing lately with my own windsor configurations, which is pretty minor - but saves me a little grief when it comes to refactoring etc.

Basically I have this extension method:


public static ComponentRegistration<S> RegisterTransient<S>(this IWindsorContainer container, ComponentRegistration<S> registration)

{

  container.Register(registration.LifeStyle.Transient);

  return registration;

}



Which then lets me do this:


var serviceA = container.RegisterTransient(Component.For<IStaffRepository>()

  .ImplementedBy<StaffRepositoryA>());


var serviceB = container.RegisterTransient(Component.For<IStaffRepository>()

  .ImplementedBy<StaffRepositoryB>());

 

container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

  .ServiceOverrides(ServiceOverride.ForKey("Repositories").Eq(serviceB.Name, serviceA.Name)));

 

var staffService = (StaffService)container.Resolve<IStaffService>();

 

Assert.IsType<StaffRepositoryB>(staffService.Repositories[0]);

Assert.IsType<StaffRepositoryA>(staffService.Repositories[1]);



notice the lack of strings when registering service overrides... it's a minor thing, but I find it quite handy... plus it generally makes it easier to identify the lifestyle of the components being registered because it's a little more in your face, i.e. your making an explicit decision... though anywhere that lifestyle poses a risk you should obviously be writing some unit tests to verify your getting the expected behavior when resolving that service anyway.

Also, while looking at ComponentRegistration<S> -the other nice thing about the fluent component registration is it works quite well for add-ons that introduce their own services which aren't loaded into a seperate app domain or child kernel ...

Just give the add-in an installation "helper" which only exposes a method taking a ComponentRegistration<S> for registering the component... you can then defer when those services are actually registered in the kernel, and can use the names of the components or other info to unregister them if the add-in is turned off (obviously this is a rainy day scenario and there are problems with this approach, but so far I've found it to work quite well).

posted @ Saturday, September 06, 2008 9:13:02 AM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
If you recall when configuring the container via xml you can do a service override like so:

<configuration>

 

    <components>

        <component id="smtp.sender"

            service="Namespace.IEmailSender, AssemblyName"

            type="Namespace.SmtpMailSender, AssemblyName" />

 

        <component id="sendmail.sender"

            service="Namespace.IEmailSender, AssemblyName"

            type="Namespace.SendMailEmailSender, AssemblyName" />

 

        <component id="newsletter"

            type="Namespace.NewsLetterSenderService, AssemblyName">

 

            <parameters>

                <sender>${smtp.sender}</sender>

            </parameters>

 

        </components>

 

    </components>

 

</configuration>


Check out the documentation on the castle site for some more details.

I recently got an email question around how to do this with the fluent interface - unfortunately with the XML, Binsor and Fluent interfaces all being used for registering and configuring the MicroKernel/Windsor Container the documentation is a little patchy across all three (with XML of course having the best coverage) - so here's an example of service override for the fluent interface.

First off the various services we'll be wiring up in this example.

public interface IStaffService

{

}

 

public class StaffService : IStaffService

{

  public IStaffRepository Repository { get; set; }

}

 

public interface IStaffRepository

{

}

 

public class StaffRepositoryA : IStaffRepository

{

}

 

public class StaffRepositoryB : IStaffRepository

{

}


And now the actual tests..

public class ServiceOverrideTests

{

  private WindsorContainer container;

 

  public ServiceOverrideTests()

  {

    container = new WindsorContainer();     

    container.Register(Component.For<IStaffRepository>().Named("repository.staff.a").ImplementedBy<StaffRepositoryA>().LifeStyle.Transient);

    container.Register(Component.For<IStaffRepository>().Named("repository.staff.b").ImplementedBy<StaffRepositoryB>().LifeStyle.Transient);

  }

 

  [Fact]

  public void ByDefaultStaffServiceWiredUpToFirstServiceRegistered()

  {

    container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>().LifeStyle.Transient);

 

    var staffService = (StaffService)container.Resolve<IStaffService>();

 

    Assert.IsType<StaffRepositoryA>(staffService.Repository);     

  }   

 

  [Fact]

  public void WithServiceOverrideCanPickImplmentationByKey()

  {

    container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

                        .ServiceOverrides(ServiceOverride.ForKey("Repository").Eq("repository.staff.b")).LifeStyle.Transient);

 

    var staffService = (StaffService)container.Resolve<IStaffService>();

 

    Assert.IsType<StaffRepositoryB>(staffService.Repository); 

  }

}


With .ServiceOverrides(ServiceOverride.ForKey("Repository").Eq("repository.staff.b")) being the code we're interested in... obviously if it was a constructor override we'd be using the name of the parameter in the constructor.

The Eq method can also take of an array of strings... which, you guessed it, means we can handle arrays of services as well ... which can be quite handy if order is important to some kind of service you're building where there are multiple contributors or some form of pipeline, lets take a look at that:

public class StaffService : IStaffService

{

  public IStaffRepository[] Repositories { get; set; } // <- is now an array of staff repository...

}


And the associated test - notice we just pass in a list of the service names...

[Fact]

public void WithServiceOverrideCanPickImplmentationByKey()

{

  container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

                      .ServiceOverrides(ServiceOverride.ForKey("Repositories").Eq("repository.staff.b", "repository.staff.a")).LifeStyle.Transient);

 

  var staffService = (StaffService)container.Resolve<IStaffService>();

 

  Assert.IsType<StaffRepositoryB>(staffService.Repositories[0]);

  Assert.IsType<StaffRepositoryA>(staffService.Repositories[1]);

}


Hopefully this proves useful to Jason (who sent me the email) and anyone else who's getting started with windsor and strugling a little to setup their container.
posted @ Saturday, September 06, 2008 8:29:15 AM (New Zealand Standard Time, UTC+12:00)    Comments [4] | |
# Wednesday, July 23, 2008
So I see more people rewriting my container tutorials lately...

First we have the unity tutorials - as covered by Michael McGuire... which I mentioned a while back.

Now we have the binsor tutorials which have sprung up lately - from ruprict covering the same concepts, but with Binsor syntax - which is quite handy for those that are boo-inclined!

I also believe a set of Ninject tutorials are being written by Simone Chiaretta (codeclimber) in his spare time as well (and who is not jealous of Ninject's website! ;o)

It's encouraging to see interest still growing in IoC on the .Net Framework.

.Net | IoC | Unity | windsor | binsor
posted @ Wednesday, July 23, 2008 1:42:46 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Sunday, December 02, 2007
So a quick observation on the alt.net conference list:

"You’ll be happy to know then that in the new WPF Composite work we are doing, the DI/IOC mechanism will be decoupled and pluggable. Actually the next version of Entlib will be the same. There’s a new Dependency Injection block that will allow you to plug-in the container of your choice."

Which was posted on the alt.net conference yahoo list by by Glen Block from Microsoft.

I think this is very good news, at least for the WPF composite work they're doing - it might make it a great deal more appealing to me then the CAB was (I was never a big fan of the CAB because it didn't integrate well with the other stacks of technologies that made me productive).

I'm fairly ambivalent about the Enterprise Libraries upcoming pluggable IoC support however - surely the overlap between it and the facilities and services already provided by the IoC container you'd be plugging into would be great ... and IoC is only part of that story... for a number of common services (i.e. logging, transactions etc.) you're going to have create appropriate wrappers and sandwich things into the containers "abstracted" view of the world, or face tightly coupling your application to the Enterprise Library, I'm not sure there is much of a value proposition there... though I'm open to being educated if any P&P Microsoft people happen to read this.

Interestingly enough has picked up on this slip from Glen and noted that it also implies Microsoft are writing yet another IoC container that will probably ship with EntLib & the WPF composite work (in whatever shape it eventually takes) and they ask the question "why oh why!" .

Personally I think it makes good sense to provide an out of the box IoC container, with it the product is far more accessible to new developers and people reviewing the technology - especially when you consider that:
  • If support was added into say the Castle Windsor container, it wouldn't see an official release until RC4 was made public - and until then would be in a state of flux as part of the castle trunk.
  • People would expect Microsoft to "suggest" an OSS container that works best with their offering - and playing favorites with the .Net OSS community could only do harm to the ecology I feel.
  • Microsoft retain consistency with their existing approach of providing an entire stack of technologies for you to get the job done, if that's what your like/want or are told you want. 
  • They can provide a set of consistent tutorials and training materials for developers to "get up to speed" with for the product, without having to provide umpteen alternative examples for different containers, or explain why the container terminology is slightly different to the product terminology.
So in short, I think it's a positive sign, not a negative one, even if another container is introduced into the mix - I'll be interested in seeing just how they do it (both the container, and the extension points to allow for plugging in a different container)... Though it could just be a hack using IServiceProvider, I wonder if perhaps they may need to go a bit further, so they can register services into the plugged in container with the appropriate lifestyle and configuration etc.

Edit: I just noticed Ayende posted about this as well...  he seems pretty well aligned with the "why oh why" viewpoint, perhaps I'm missing something - but I just don't see it being all that practical in some scenarios to provide a product that wont work without the developer going through a separate selection process to pick an IoC container, if they don't already use one from the OSS community.
posted @ Sunday, December 02, 2007 12:08:07 PM (New Zealand Daylight Time, UTC+13:00)    Comments [1] | |
# Wednesday, May 30, 2007
I've been getting a few questions about different aspects of the container tutorials series I posted a while back - while the series is not finished, neither is it forgotten, I've collated information regarding the series into a topic on my wiki and I'll keep this up to date until I've finished the series off.

I also notice Sam Gentile has posted that he's taking the plunge into learning about castle's Windsor container... good to hear :)


castle | IoC | wiki
posted @ Wednesday, May 30, 2007 5:30:43 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Sunday, April 29, 2007
14_startable_facility.png

So this time we're going to have a look at the startable facility (you can find more info on it here in the wiki) - the concept of the startable facility is to ensure that components are started as soon as possible, which translates to as soon as all dependencies are available. 

Effectively what happens is you create a component, and implement a special interface called IStartable, which looks like this and is found in the Castle.Core assembly.

/// <summary>

/// Interface for components that wish to be started by the container

/// </summary>

public interface IStartable

{

    /// <summary>

    /// Starts this instance.

    /// </summary>

    void Start();

 

    /// <summary>

    /// Stops this instance.

    /// </summary>

    void Stop();

}


And then the startable facility detects any components registered in the container which implement the IStartable interface and determines if they have any dependencies which still need to be satisfied, if not, then the container will Resolve the component, and start it immediately (by invoking the IStartable.Start method on it) otherwise it's added to a list of services awaiting startup.

From then on, as components are registered in the container the startable facility will check the list of services awating startup, to see if any of them have all their dependencies available now, if so it will then Resolve the service and again invoke IStartable.Start on it.

Now at this point it's worth noting that Start is not executed asynchronously - if you block within the Start method then your container will halt loading the configuration etc. till it completes... be careful not to slow down your container startup too much with slow blocking operations with the Start() method.

So let's get into some code... first off I'm going to create a simple http listening service which is capable of serving up a single file... exciting stuff!

Here's the code:

public class LameHttpFileServer : IStartable

{

    private string _path;

    private HttpListener _listener;

    private Thread _listenerThread;

    private ILogger _logger;

 

    public LameHttpFileServer(string prefix, string path)

    {

        _path = path;

        _listener = new HttpListener();

        _listener.Prefixes.Add(prefix);

    }

 

    public ILogger Logger

    {

        get

        {

            if (_logger == null) _logger = NullLogger.Instance;

            return _logger;

        }

        set { _logger = value; }

    }

 

    public void Start()

    {

        Logger.Debug("Starting LameWebService...");

        _listener.Start();

        _listenerThread = new Thread(RequestWorker);

        _listenerThread.Start();

        Logger.Info("LameWebService Started.");

    }

 

    public void Stop()

    {

        Logger.Debug("Stopping LameWebService...");

        _listenerThread.Abort();

        _listener.Stop();

        Logger.Info("Stopped LameWebService.");

    }

 

    private void RequestWorker()

    {

        while (true)

        {

            HttpListenerContext context = null;

 

            try

            {

                context = _listener.GetContext();

            }

            catch (ObjectDisposedException)

            {

                return;

            }

 

            ServeContent(context.Response, _path);

        }

    }

 

    private void ServeContent(HttpListenerResponse response, string path)

    {

        string content = File.ReadAllText(path);

        byte[] buffer = Encoding.UTF8.GetBytes(content);

        response.ContentLength64 = buffer.Length;

 

        Stream output = response.OutputStream;

        output.Write(buffer, 0, buffer.Length);

        output.Close();

    }

}


Now, this class doesn't have any constructor dependencies (beyond a little configuration) but we do have a Setter dependency on an ILogger service - ILogger is actually a generic abstract of a logger for a logging framework (a logger being a named/scoped class supporting a number of generic message writing methods) out of the box Castle provides support for both nlog and log4net, however it also contains some lightweight loggers, such as a console logger, which means you can avoid having to write any logging configuration files... so we're going to use that this time... because the loggers are assigned by the container, there's not need to actually reference the type the logger is logging "for", because the container knows that implicitly.

Now let's have a look at the container configuration:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <facilities>

      <facility id="startable.facility"

        type="Castle.Facilities.Startable.StartableFacility, Castle.MicroKernel" />

 

      <facility id="logging.facility"

        type="Castle.Facilities.Logging.LoggingFacility, Castle.Facilities.Logging"

        loggingApi="console" />                         

 

  </facilities>

    <components>

 

      <component id="serves->lame.html"

                type="IoC.Tutorials.Part14.LameHttpFileServer, IoC.Tutorials.Part14">

        <parameters>

          <prefix>http://*:8089/</prefix>

          <path>lame.html</path>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


As you can see we have declared two facilities, one for handling the auto-wiring of Loggers into any components with ILogger constructor parameters or setter dependencies, and secondly the startable facility, which will take care of automatically starting our LameHttpFileServer for us.

Now, notice we're referencing a file called lame.html - heres what that looks like:

<html>

    <body>

        <h1>Lame.html</h1>

        <h2>Welcome to lame.html file</h2>

        <p>This is the contents of the lame.html file, neat huh?</p>

    </body>

</html>


Now done to business, let's look at the program that's using this server...

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    GetPage();

 

    container.Dispose();

 

    GetPage();

 

    Console.Read();

}

 

private static void GetPage()

{           

    Console.WriteLine("\r\nClient: requesting http://localhost:8089/ ...");

    try

    {

        WebClient client = new WebClient();

        string content = client.DownloadString("http://localhost:8089/");

        Console.WriteLine("Client: success, content follows.\r\n\r\n {0}", content);

    }

    catch (WebException ex)

    {

        Console.WriteLine("Client: Exception occured, message: {0}", ex.Message);

    }

}


As you can see what we're doing is:

  1. Constructing the container using the configuration.
  2. Calling the GetPage method, which will attempt to download the lame.html file from our server (which the container should have started automatically for us)
  3. Disposing of the container (any guesses what that will do?)
  4. And finally calling the GetPage method again, to see if our server is still running.
So, running the program gives us these results:

[Debug] 'IoC.Tutorials.Part14.LameHttpFileServer' Starting LameWebService...
[Info] 'IoC.Tutorials.Part14.LameHttpFileServer' LameWebService Started.

Client: requesting http://localhost:8089/ ...
Client: success, content follows.

 <html>
    <body>
        <h1>Lame.html</h1>
        <h2>Welcome to lame.html file</h2>
        <p>This is the contents of the lame.html file, neat huh?</p>
    </body>
</html>

[Debug] 'IoC.Tutorials.Part14.LameHttpFileServer' Stopping LameWebService...
[Info] 'IoC.Tutorials.Part14.LameHttpFileServer' Stopped LameWebService.

Client: requesting http://localhost:8089/ ...
Client: Exception occurred, message: Unable to connect to the remote server

As you can see before we disposed of the container our request for the file worked just fine, but after the container had been disposed, it appears the file service has been stopped, and so our client was unable to connect... what caused this?

Well the way the startable service is implemented, it actually applies a couple of lifecycle concerns - a concern is effectively a bit of code that executes when what it's concerned in occurs, in these case the startable facility adds two concerns to a startable component's model.

The first "concern" is a commission concern, which invokes the Start method upon the component entering the commission step of it's lifecycle, which is immediately after the component instance has been constructed and all it's dependencies and configuration injected. 

The second concern is a "decommission" concern, which occurs upon the component is being decommissioned (ie. disposed of, released or purged from the container) this happens to all components the container is holding onto when it is disposed, or when an individual component is released - however in the case of components with a singleton lifestyle, you can't actually release the component prior to disposing of the container (because that would violate the lifestyle) ... so doing something like this:

LameHttpFileServer server = container.Resolve<LameHttpFileServer>();

container.Release(server);


In place of disposing the container won't stop the service if it's a singleton....

One last though - what would happen if we changed our components lifestyle to [Transient] instead of the default of singleton, let's create a simple class for testing this idea:

[Transient]

public class StartableExperiment : IStartable

{

    private static int _count;

    private int _number;

 

    public StartableExperiment()

    {

        _number = ++_count;

    }

 

    public void Start()

    {

        Console.WriteLine("Started #{0}", _number);

    }

 

    public void Stop()

    {

        Console.WriteLine("Stopped #{0}", _number);

    }

}


Now let's write some code to test it... we'll just register the component in code, to avoid having to change our config...

Here's the program itself...

WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

container.AddComponent("exp", typeof(StartableExperiment));

 

StartableExperiment exp1 = container.Resolve<StartableExperiment>();

container.Release(exp1);

StartableExperiment exp2 = container.Resolve<StartableExperiment>();

container.Release(exp2);

 

container.Dispose();


And the results:

Started #1
Started #2
Stopped #2
Started #3
Stopped #3
Stopped #1


So what's happened is that immediately upon registration a component is created... and can't be disposed (because we can't get a hold of the instance to release it) until the container is disposed... but for the couple of calls to Resolve and Release you can see the StartableExperiment instances are started & stopped during commission & decommission steps in the components life cycle as expected.

So that brings this look at the startable facility to an end... next time we might have another quick look at life cycles to see how else we can use this concept when build components, and maybe after that we'll have a look at some of other lifestyles which are available "out of the box" and how to write our own.
posted @ Sunday, April 29, 2007 4:51:25 PM (New Zealand Standard Time, UTC+12:00)    Comments [3] | |
# Saturday, April 28, 2007
13_injecting_service_arrays.png
So this time we're going to look at injecting service arrays ... if you haven't read part 12, it might pay to have a look at that first - this part follows on from the examples presented there.

So this should be reasonably quick, we're just going to rework the Part 12 solution so we don't need decorators... why would we do this, well in this case I feel that rewiring decorators (ie. changing orders, or disabling one of the decorators temporarily) isn't completely intuitive, especially when you have a long chain, it's easy to make mistakes.

So what's the plan, well first off let's implement an abstract class for our calculators:

public abstract class AbstractCalculator

{

    public abstract decimal Calculate(decimal currentTotal, Order order);

}


Now we can rework the existing decorators and default calculator to be implementations of the abstract caculator, so here goes:

First off the the logic in the DefaultCostCalculator will be moved into a class called TotalCalculator :

public class TotalCalculator : AbstractCalculator

{

    private decimal CalculateTotal(Order order)

    {

        decimal total = 0;

 

        foreach (OrderItem item in order.Items)

        {

            total += (item.Quantity*item.CostPerItem);

        }

 

        return total;

    }

 

    public override decimal Calculate(decimal currentTotal, Order order)

    {

        return currentTotal + CalculateTotal(order);

    }

}


And then for the gst calculator, we do much the same thing:

public class GstCalculator : AbstractCalculator

{

    private decimal _gstRate = 1.125m;

 

    public decimal GstRate

    {

        get { return _gstRate; }

        set { _gstRate = value; }

    }

 

    private bool IsNewZealand(Order order)

    {

        return (order.CountryCode == "NZ");

    }

 

    public override decimal Calculate(decimal currentTotal, Order order)

    {

        if (IsNewZealand(order))

        {

            return (currentTotal*_gstRate);

        }

 

        return currentTotal;

    }

}


And finally the shipping calculator:

public class ShippingCalculator : AbstractCalculator

{

    private decimal _shippingCost = 5.0m;

    private decimal _fragileShippingPremium = 1.5m;

 

    public decimal ShippingCost

    {

        get { return _shippingCost; }

        set { _shippingCost = value; }

    }

 

    public decimal FragileShippingPremium

    {

        get { return _fragileShippingPremium; }

        set { _fragileShippingPremium = value; }

    }

 

    private decimal GetShippingTotal(Order order)

    {

        decimal shippingTotal = 0;

 

        foreach (OrderItem item in order.Items)

        {

            decimal itemShippingCost = ShippingCost*item.Quantity;

            if (item.IsFragile) itemShippingCost *= FragileShippingPremium;

            shippingTotal += itemShippingCost;

        }

 

        return shippingTotal;

    }

 

    public override decimal Calculate(decimal currentTotal, Order order)

    {

        return currentTotal + GetShippingTotal(order);

    }

}


Now, our original DefaultCostCalculator is reworked to use an array of AbstractCalculators to compute the total cost for an order:

public class DefaultCostCalculator : ICostCalculator

{

    private AbstractCalculator[] _calculators;

 

    public DefaultCostCalculator(AbstractCalculator[] calculators)

    {

        _calculators = calculators;

    }

 

    public decimal CalculateTotal(Order order)

    {

        decimal currentTotal = 0;

 

        foreach (AbstractCalculator calculator in _calculators)

        {

            currentTotal = calculator.Calculate(currentTotal, order);

        }

 

        return currentTotal;

    }

}


Notice it takes an array of AbstractCalculator's as a constructor dependency... just like we did for configuration parameters in the early parts of this container tutorial series, we can actually pass arrays of dependencies to a component as well, so last of all let's see the container configuration:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

 

      <component id="calc.gst"

                service="IoC.Tutorials.Part13.AbstractCalculator, IoC.Tutorials.Part13"

                type="IoC.Tutorials.Part13.GstCalculator, IoC.Tutorials.Part13">

        <parameters>

          <GstRate>1.20</GstRate>

          <!-- GST is now 20% -->

        </parameters>

      </component>

 

      <component id="calc.shipping"

          service="IoC.Tutorials.Part13.AbstractCalculator, IoC.Tutorials.Part13"

          type="IoC.Tutorials.Part13.ShippingCalculator, IoC.Tutorials.Part13">

        <parameters>

          <FragileShippingPremium>0.0</FragileShippingPremium>

          <!-- No fragile goods premium any more-->

        </parameters>

      </component>

 

      <component id="calc.total"

        service="IoC.Tutorials.Part13.AbstractCalculator, IoC.Tutorials.Part13"

          type="IoC.Tutorials.Part13.TotalCalculator, IoC.Tutorials.Part13" />

 

      <component id="costCalculator.default"

                service="IoC.Tutorials.Part13.ICostCalculator, IoC.Tutorials.Part13"

                type="IoC.Tutorials.Part13.DefaultCostCalculator, IoC.Tutorials.Part13">

        <parameters>

          <calculators>

            <array>

              <value>${calc.total}</value>

              <value>${calc.shipping}</value>

              <value>${calc.gst}</value>

            </array>

          </calculators>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


Notice the default caculator now takes our 3 calculators as members of an array, and if we want to change the order in which they are evaluated, it's trivial to just move them around within the <array /> node, or to comment certain ones out.

And just to demonstrate that nothing has changed, the code for the program in part 13 is identical to part 12:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    Order order1 = new Order();

    order1.CountryCode = "NZ";

    order1.Items.Add(new OrderItem("water", 10, 1.0m, false));

    order1.Items.Add(new OrderItem("glass", 5, 20.0m, true));

 

    Order order2 = new Order();

    order2.CountryCode = "US";

    order2.Items.Add(new OrderItem("sand", 50, 0.2m, false));

 

    ICostCalculator costCalculator = container.Resolve<ICostCalculator>();

    Console.WriteLine("Cost to deliver Order 1: {0}", costCalculator.CalculateTotal(order1));

    Console.WriteLine("Cost to deliver Order 2: {0}", costCalculator.CalculateTotal(order2));

 

    Console.Read();

}


And the results are the same too:

Cost to deliver Order 1: 192.0000
Cost to deliver Order 2: 260.0


Beautiful :)

The next part will have a quick look at the "Startable" facility, enjoy.





posted @ Saturday, April 28, 2007 1:52:38 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
12_decorators.png
So... Decorators (for those who don't know, or don't remember) are a classic design pattern - have a look at the wikipedia entry if your curious on doing any background reading.

Up until now we've been creating abstractions and swapping implementations, but here we are going to chain implementations... so for this example we have an Order class which contains a bunch of order items, here's how that looks:

Order.cs

public class Order

{

    private string _countryCode;

    private readonly List<OrderItem> _items = new List<OrderItem>();

 

    public List<OrderItem> Items

    {

        get { return _items; }

    }

 

    public string CountryCode

    {

        get { return _countryCode; }

        set { _countryCode = value; }

    }

}


OrderItem.cs

public class OrderItem

{

    private string _name;

    private bool _isFragile;

    private int _quantity;

    private decimal _costPerItem;

 

    public OrderItem(string name, int quantity, decimal costPerItem, bool isFragile)

    {

        _name = name;

        _quantity = quantity;

        _costPerItem = costPerItem;

        _isFragile = isFragile;

    }

 

    public bool IsFragile

    {

        get { return _isFragile; }

        set { _isFragile = value; }

    }

 

    public int Quantity

    {

        get { return _quantity; }

        set { _quantity = value; }

    }

 

    public decimal CostPerItem

    {

        get { return _costPerItem; }

        set { _costPerItem = value; }

    }

 

    public string Name

    {

        get { return _name; }

        set { _name = value; }

    }

}


And now we have an interface that a class can implement to calculate the cost of an order:

public interface ICostCalculator

{

    decimal CalculateTotal(Order order);

}


And last of all we have an implementation of the cost calculator, which calculates the base cost of an order based on quantities and per-item costs:

public class DefaultCostCalculator : ICostCalculator

{

    public decimal CalculateTotal(Order order)

    {

        decimal total = 0;

 

        foreach (OrderItem item in order.Items)

        {

            total += (item.Quantity*item.CostPerItem);

        }

 

        return total;

    }

}


Pretty simple, so what about the program itself... well here it is, we just have 2 different orders we are calculating the total cost for:

internal class Program

{

    private static void Main(string[] args)

    {

        WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

        Order order1 = new Order();

        order1.CountryCode = "NZ";

        order1.Items.Add(new OrderItem("water", 10, 1.0m, false));

        order1.Items.Add(new OrderItem("glass", 5, 20.0m, true));

 

        Order order2 = new Order();

        order2.CountryCode = "US";

        order2.Items.Add(new OrderItem("sand", 50, 0.2m, false));

 

        ICostCalculator costCalculator = container.Resolve<ICostCalculator>();

        Console.WriteLine("Cost to deliver Order 1: {0}", costCalculator.CalculateTotal(order1));

        Console.WriteLine("Cost to deliver Order 2: {0}", costCalculator.CalculateTotal(order2));

 

        Console.Read();

    }

}


Our configuration (predictably) just had the default implementation of the cost calculator registered:

<component id="costCalculator.default"

          service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

          type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />


Now lets see the output of running it:

Cost to deliver Order 1: 110.0
Cost to deliver Order 2: 10.0

So that seems OK... But I live in New Zealand, and in New Zealand we have GST (Goods and Services Tax) which means that I need to add another 12.5% to the total value of an order for NZ customers... so I could modify the default shipping calculator... but that's going to get ugly fast as more requirements come in (and more configuration needs to be exposed) - so instead I'll create a decorator for the cost calculator, just for doing GST:

public class GstCostCalcualtorDecoarator : ICostCalculator

{

    private readonly ICostCalculator _innerCalculator;

    private decimal _gstRate = 1.125m;

 

    public GstCostCalcualtorDecoarator(ICostCalculator innerCalculator)

    {

        _innerCalculator = innerCalculator;

    }

 

    public decimal GstRate

    {

        get { return _gstRate; }

        set { _gstRate = value; }

    }

 

    private bool IsNewZealand(Order order)

    {

        return (order.CountryCode == "NZ");

    }

 

    public decimal CalculateTotal(Order order)

    {

        decimal innerTotal = _innerCalculator.CalculateTotal(order);

 

        if (IsNewZealand(order))

        {

            innerTotal = (innerTotal*_gstRate);

        }

 

        return innerTotal;

    }

}


Notice it's dependency on ICostCalculator, and that it actually invokes the inner calculator to get a total and then "decorates" the total (by adding the 12.5% when the country for the order is New Zealand).

Now we can actually wire this up in our container without changing any of our application code... let's look at that:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

 

      <component id="costCalculator.gstDecorator"

                service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

                type="IoC.Tutorials.Part12.GstCostCalcualtorDecoarator, IoC.Tutorials.Part12">

        <parameters>

          <innerCalculator>${costCalculator.default}</innerCalculator>

        </parameters>

      </component>

 

      <component id="costCalculator.default"

                service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

                type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />

 

    </components>

  </castle>

 

</configuration>


Notice that the GSTdecorator is registered first (so it will be the default implementation of the ICostCalculator service) and it's inner calculator is wired to our default cost calculator... but proof is in the pudding, lets see what the results of running the program are now:

Cost to deliver Order 1: 123.7500
Cost to deliver Order 2: 10.0


Great, so our New Zealand order is now ($110 * 1.125 = $123.75) - but our United states order is still at the original $10 dollars... but we forgot to calculate shipping... so let's add another decorator.

public class ShippingCostCalculatorDecorator : ICostCalculator

{

    private readonly ICostCalculator _innerCalculator;

    private decimal _shippingCost = 5.0m;

    private decimal _fragileShippingPremium = 1.5m;

 

    public ShippingCostCalculatorDecorator(ICostCalculator innerCalculator)

    {

        _innerCalculator = innerCalculator;

    }

 

    public decimal ShippingCost

    {

        get { return _shippingCost; }

        set { _shippingCost = value; }

    }

 

    public decimal FragileShippingPremium

    {

        get { return _fragileShippingPremium; }

        set { _fragileShippingPremium = value; }

    }

 

    public decimal CalculateTotal(Order order)

    {

        decimal innerTotal = _innerCalculator.CalculateTotal(order);

        return innerTotal + GetShippingTotal(order);

    }

 

    private decimal GetShippingTotal(Order order)

    {

        decimal shippingTotal = 0;

 

        foreach (OrderItem item in order.Items)

        {

            decimal itemShippingCost = ShippingCost*item.Quantity;

            if (item.IsFragile) itemShippingCost *= FragileShippingPremium;

            shippingTotal += itemShippingCost;

        }

 

        return shippingTotal;

    }

}


And of course, we need to wire that up as well:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

 

      <component id="costCalculator.shippingDecorator"

          service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

          type="IoC.Tutorials.Part12.ShippingCostCalculatorDecorator, IoC.Tutorials.Part12">

        <parameters>

          <innerCalculator>${costCalculator.gstDecorator}</innerCalculator>

        </parameters>

      </component>

 

      <component id="costCalculator.gstDecorator"

                service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

                type="IoC.Tutorials.Part12.GstCostCalcualtorDecoarator, IoC.Tutorials.Part12">

        <parameters>

          <innerCalculator>${costCalculator.default}</innerCalculator>

        </parameters>

      </component>

 

      <component id="costCalculator.default"

                service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

                type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />

 

    </components>

  </castle>

 

</configuration>


Notice the chain, now we have Shipping -> GST -> Default Calculator .. so running the app again we can see the new totals:

Cost to deliver Order 1: 211.2500
Cost to deliver Order 2: 260.0


Now there's a small problem here... we're calculating GST before shipping, this actually should be the other way round... think about what you would have to do to change this in a program normally - ugh!  But of course decorators and IoC containers are a great fit, we'll just change the order of decorators, and while we're at it, lets make GST 20% and no longer charge a premium for shipping fragile goods... easy!

<components>

 

  <component id="costCalculator.gstDecorator"

            service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

            type="IoC.Tutorials.Part12.GstCostCalcualtorDecoarator, IoC.Tutorials.Part12">

    <parameters>

      <innerCalculator>${costCalculator.shippingDecorator}</innerCalculator>

      <GstRate>1.20</GstRate> <!-- GST is now 20% -->

    </parameters>

  </component>

 

  <component id="costCalculator.shippingDecorator"

      service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

      type="IoC.Tutorials.Part12.ShippingCostCalculatorDecorator, IoC.Tutorials.Part12">

    <parameters>

      <innerCalculator>${costCalculator.default}</innerCalculator>         

      <FragileShippingPremium>0.0</FragileShippingPremium> <!-- No fragile goods premium any more-->

    </parameters>

  </component>

 

  <component id="costCalculator.default"

            service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"

            type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />

 

</components>


And for anyone sad enough to be checking the results with a calculator (or with the human equivalent ;o) we'll run the program one last time:

Cost to deliver Order 1: 192.0000
Cost to deliver Order 2: 260.0


Now one thing to keep in mind is that so far we've been decorating return values... but you can also decorate methods with logic that occurs before invoking the inner service - a common example of this might be to validate something before it's committed to a repository (and perhaps throwing an exception if it's not OK) - and now suddenly you can turn validation on or off at the configuration level.

Next time we'll have a look at another way of writing this functionality without using decorators, stay tuned.
posted @ Saturday, April 28, 2007 12:27:50 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Wednesday, April 25, 2007
11_factories.png
So most all of us are familiar with factories, and at first glance it seems an IoC container removes the need for having to write our own... but this isn't quite the case - for the container to be able create a component it needs:
  • A publicly accessible constructor.
  • All dependencies to be registered in the container.
  • Mechanisms to allow for configuration and dependencies to be injected via constructors, or properties.
Which is fine for classes you own, but what about those that you don't - well you have a few options, but one of the easy options is to create a factory and get the container to use the factory for creating instances - to do this we'll be using a facility.

Facilities are "add-ins" for the container, they can be registered in the container, and augment what the container is capable of doing - there are a lot of facilities for the container, and many of them are documented (to varying degrees) on the castle project wiki ... we will be using a couple of different facilities in this part, first off will be the factory support facility.

So let's start off with a class that's supplied to us by a 3rd party... I'm just going to make one as an example, to keep things simple, called the Sms Service, for sending simple messages to cellular phones...

public class SmsService : ISmsService

{

    private SmsConfig _config;

 

    public void SetConfig(SmsConfig config)

    {

        _config = config;

    }

 

    public void SendMessage(string number, string message)

    {

        Console.WriteLine("SMS message: {0} sent to: {1} with account: {2}", message, number, _config.UserName);

    }

 

    public class SmsConfig

    {

        private string _userName;

        private string _password;

        private int _retryAttempts;

 

        internal string UserName

        {

            get { return _userName; }

        }

 

        internal string Password

        {

            get { return _password; }

        }

 

        public int RetryAttempts

        {

            get { return _retryAttempts; }

            set { _retryAttempts = value; }

        }

 

        public void SetCredentials(string userName, string password)

        {

            _userName = userName;

            _password = password;

        }

    }

}


It also has a corresponding interface:

public interface ISmsService

{

    void SendMessage(string number, string message);

}


Now the point is that this class can not be constructred and configured by the container "as-is" because it requires something like this to happen:

SmsService service = new SmsService();

 

SmsService.SmsConfig config = new SmsService.SmsConfig();

config.SetCredentials("joe", "secret");

config.RetryAttempts = 3;

 

service.SetConfig(config);


Ack! Which doesn't fit in nicely with our concepts of constructor and setter injection for configuration...  so the answer is first off, to write a factory... can you guess what it'll look like?

public class SmsServiceFactory

{

    public ISmsService CreateService()

    {

        SmsService service = new SmsService();

 

        SmsService.SmsConfig config = new SmsService.SmsConfig();

        config.SetCredentials("joe", "secret");

        config.RetryAttempts = 3;

 

        service.SetConfig(config);

 

        return service;

    }

}


Well almost - but we don't like hard coding credentials, so we might refactor it a little... to say something like this:

public class SmsServiceFactory

{

    private string _userName;

    private string _password;

    private int _retryAttempts = 3;

 

    public SmsServiceFactory(string userName, string password)

    {

        _userName = userName;

        _password = password;

    }

 

    public int RetryAttempts

    {

        get { return _retryAttempts; }

        set { _retryAttempts = value; }

    }

 

    public ISmsService CreateService()

    {

        SmsService service = new SmsService();

 

        SmsService.SmsConfig config = new SmsService.SmsConfig();

        config.SetCredentials(_userName, _password);

        config.RetryAttempts = _retryAttempts;

 

        service.SetConfig(config);

 

        return service;

    }

}


Now how do we use this factory in lieu of registering the SmsService itself in the container... well first off, we need to add in the factory support facility... which is placed within a new part of the castle configuration we haven't seen until now (so far we've only be using the <components /> section) - here's how that looks:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <facilities>

 

      <facility

        id="factorysupport"

        type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />

 

    </facilities>


Nothing much to it, but now the factory support facility has augmented our container, so we can do this:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <facilities>

 

      <facility

        id="factorysupport"

        type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />

 

    </facilities>

    <components>

 

      <component id="smsService.Factory"

                type="IoC.Tutorials.Part11.SmsServiceFactory, IoC.Tutorials.Part11">

        <parameters>

          <userName>joe</userName>

          <password>secret</password>         

        </parameters>

      </component>

 

      <component id="smsService.default"

                type="IoC.Tutorials.Part11.ISmsService, IoC.Tutorials.Part11"

                factoryId="smsService.Factory"

                factoryCreate="CreateService" />

 

    </components>

  </castle>

 

</configuration>


Notice that we've registered our factory as a component, and called it smsService.Factory - and then we've registered the smsService.default (interface only) and added a couple of additional attributes, factoryId (which references our factory component) and factoryCreate - the name of the method in the factory which is responsible for creating instances of our sms service.

Because we now have the factory support facility installed, whenever a component is registered that facility will inspect it and see if the factoryId attribute appears in the components configuration and consequently defer it's activation to the referenced factory - pretty cool huh?

So, the million dollar question, does it work?  Well lets see... here's our code:

static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    ISmsService smsService = container.Resolve<ISmsService>();

    smsService.SendMessage("+465556555", "testing testing...1.2.3");

 

    Console.Read();

}


And the output:

SMS message: testing testing...1.2.3 sent to: +465556555 with account: joe

At this point I was going to take a quick look into another factory-related facility, the TypedFactory, but it's currently broken in the main trunk ;o) so we'll wait until that's been resolved before finishing off this post.

Next time we'll have a quite look at revisiting a class design pattern, the decorator, when using the Windsor container.
posted @ Wednesday, April 25, 2007 7:11:04 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
10_setter_injection.png
So, lets have a look at setter injection - for this part I'll be refactoring the example in part 9 ... so if you recall in the last part we had a class that could send messages (to the console at least) - and it had a hard-coded string being used for the format... we'll I think it would be nice to "plug in" different message formatting, if we needed to... so first thing to do is create a necessary abstraction for formatting a message - which I've called the IMessageFormatter interface:

public interface IMessageFormatter

{

    string FormatMessage(string from, string to, string body);

}


Now, our old method for formatting a message (as part of the SecretMessageSender class) used to look like this:

public void SendMessage(string to, string body)

{

    Console.WriteLine("to: {0}\r\nfrom: {1}\r\n\r\n{2}", to, _from, _encoder.Encode(body));

}


So we just refactor that out into it's own class, like so:

public class DefaultFormatter : IMessageFormatter

{

    public string FormatMessage(string from, string to, string body)

    {

        return string.Format("to: {0}\r\nfrom: {1}\r\n\r\n{2}", to, from, body);

    }

}


And update the secret message sender to use this default formatter... by default!

public class SecretMessageSender

{

    private readonly IEncoder _encoder;

    private readonly string _from;

    private IMessageFormatter _formatter = new DefaultFormatter();

 

    public SecretMessageSender(string from, IEncoder encoder)

    {

        _from = from;

        _encoder = encoder;

    }

 

    public IMessageFormatter Formatter

    {

        get { return _formatter; }

        set { _formatter = value; }

    }

 

    public void SendMessage(string to, string body)

    {

        string encodedBody = _encoder.Encode(body);

        Console.WriteLine(_formatter.FormatMessage(_from, to, encodedBody));

    }

}


Now notice we automatically create a default formatter for the class to use... so at this point we can run the program just as in part 9 (Without having to make any changes to the container configuration) and everything works as it did... however, we can also optionally override the message formatter by registering an implementation in the container... the MicroKernel is smart enough to discover any publicly accessible properties with setters, look for any implementations, and inject them if they're registered in the container.

So first off lets create a different implementation - I'm going to use NVelocity (a template engine, which is used for one of the View engines that comes with monorail) this time along with a template - so first we have the alternative message formatter class:

public class NVelocityMessageFormatter : IMessageFormatter

{

    private readonly VelocityEngine _velocity;

    private readonly Template _template;

 

    public NVelocityMessageFormatter(string templateFile)

    {

        _velocity = new VelocityEngine();

        ExtendedProperties props = new ExtendedProperties();

        _velocity.Init(props);

        _template = _velocity.GetTemplate(templateFile);

    }

 

    public string FormatMessage(string from, string to, string body)

    {

        VelocityContext context = new VelocityContext();

        context.Put("from", from);

        context.Put("to", to);

        context.Put("body", body);

        context.Put("today", DateTime.Now);

 

        StringWriter writer = new StringWriter();

        _template.Merge(context, writer);

 

        return writer.ToString();

    }

}


And of course, we also need a template file (Which we will call message.vm) - this is what our template will look like:

 To:   $to

 From: $from

 Sent: $today

 

 ----------------------

 

 $body

 

 ----------------------


And finally the last part of the puzzle is to update the container configuration to include our alternative message formatter:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="encoder.silly"

                service="IoC.Tutorials.Part10.IEncoder, IoC.Tutorials.Part10"

                type="IoC.Tutorials.Part10.SillyEncoder, IoC.Tutorials.Part10" />

 

      <component id="encoder.null"

                service="IoC.Tutorials.Part10.IEncoder, IoC.Tutorials.Part10"

                type="IoC.Tutorials.Part10.NullEncoder, IoC.Tutorials.Part10" />

 

      <component id="messageSender"

                type="IoC.Tutorials.Part10.SecretMessageSender, IoC.Tutorials.Part10">

        <parameters>SecretMessageSender

          <from>alex@bittercoder.com</from>

          <encoder>${encoder.null}</encoder>         

        </parameters>

      </component>

 

      <component id="fancyMessageFormatter"

                service="IoC.Tutorials.Part10.IMessageFormatter, IoC.Tutorials.Part10"

                type="IoC.Tutorials.Part10.NVelocityMessageFormatter, IoC.Tutorials.Part10">

        <parameters>

          <templateFile>message.vm</templateFile>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


And now if we give it a run, we get this output:

To:   hammet
From: alex@bittercoder.com
Sent: 25/04/2007 6:56:37 p.m.

----------------------

castle is great!

----------------------


So you can now see how a mix of constructor and setter injection can be used to achieve compulsory and optional dependencies - of course, we can also wire up properties to specific implementations - for instance in this last example we could change the config to read:

<component id="messageSender"

          type="IoC.Tutorials.Part10.SecretMessageSender, IoC.Tutorials.Part10">

  <parameters>SecretMessageSender

    <from>alex@bittercoder.com</from>

    <encoder>${encoder.null}</encoder>

    <Formatter>${fancyMessageFormatter}</Formatter>

  </parameters>

</component>

 

<component id="defualtMessageFormatter"

    service="IoC.Tutorials.Part10.IMessageFormatter, IoC.Tutorials.Part10"

    type="IoC.Tutorials.Part10.DefaultFormatter, IoC.Tutorials.Part10" />       

 

<component id="fancyMessageFormatter"

          service="IoC.Tutorials.Part10.IMessageFormatter, IoC.Tutorials.Part10"

          type="IoC.Tutorials.Part10.NVelocityMessageFormatter, IoC.Tutorials.Part10">

  <parameters>

    <templateFile>message.vm</templateFile>

  </parameters>

</component>


Where even though the default message formatter is registered first in the container, the fancy message formatter will be used because it's manually wired up in the messageSender's component parameters.

Next time will be having a look at factories and how to fit in with the Windsor container.
posted @ Wednesday, April 25, 2007 6:43:10 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Thursday, April 19, 2007
So the first 9 posts are up for the container tutorial series...  but I haven't made much mention of what can be done to play around with the windsor container yourself while reading this series.

Well first-off ... my thoughts on getting started with the Castle project are generally practical, first off I think it's worth grabbing the second release candidate - check out what castle can do, have a general play, maybe try to generate a monorail project and get it working... and then ... well I would probably uninstall it, and grab the latest cut of the castle project and contributed projects from svn and build it yourself using nant.

This gives you opportunities to use all the "new stuff" that gets added day by day (as well as bug fixes) but also ensures your actually capable of building and contributing patches for any issues you discover.

But that's a bit of an ask for someone experimenting, especially if you don't know anything about svn... so essentially for playing around with the basics of the windsor container, you only need 4 Castle assemblies from the bleeding edge, and I'll give them to you:

simple_container_references.png

And to make life easy I included those assemblies in a folder called "SharedLibs" as part of the following zip file, which contains the code for the first 9 parts... I'll do another code drop at the end of the container tutorials to round out the series for the sake of posterity... but everything you need for the first 9 tutorials is here:

Files for Parts 1 thru 9

Good Times ;o)


posted @ Thursday, April 19, 2007 10:31:40 PM (New Zealand Standard Time, UTC+12:00)    Comments [4] | |
9_constructor_injection.png

Constructor injection - so far inadvertantly we've been using setter inject to get our configuration information into our components... but you can also use constructors... the useful aspect of constructors is that it makes those parameters compulsory...

So lets take a look at the code for this post, first off there's an interface for a service which takes care of encoding a string for us:

public interface IEncoder

{

    string Encode(string source);

}


And then we have no classes which implement this service, one we can use when testing to not encode things at all - and another which encodes a string using our particularly strong "silly" encryption...

NullEncoder.cs

public class NullEncoder : IEncoder

{

    public string Encode(string source)

    {

        return source;

    }

}


SillyEncoder.cs

public class SillyEncoder : IEncoder

{

    private char[] _mixedUp = "YACBDFEGIHJLKMONPRSQTUWVXZ".ToCharArray();

 

    public string Encode(string source)

    {

        string upperSource = source.ToUpper();

        char[] encoded = new char[source.Length];

        for (int i = 0; i < encoded.Length; i++)

        {

            encoded[i] = MapCharacter(upperSource[i]);

        }

        return new string(encoded);

    }

 

    private char MapCharacter(char ch)

    {

        if ((ch >= 'A') && (ch <= 'Z'))

        {

            return _mixedUp[ch - 'A'];

        }

        return ch;

    }

}


When then have a class for sending messages (currently we just send it to the console, so we can print them out and paste them onto the back of postcards) ... so lets have a look at that class:

public class SecretMessageSender

{

    private readonly IEncoder _encoder;

    private readonly string _from;

 

    public SecretMessageSender(string from, IEncoder encoder)

    {

        _from = from;

        _encoder = encoder;

    }

 

    public void SendMessage(string to, string body)

    {

        Console.WriteLine("to: {0}\r\nfrom: {1}\r\n\r\n{2}", to, _from, _encoder.Encode(body));

    }

}


Notice the lack of default constructor, and that the constructor also takes an instance of type IEncoder... now Castle is smart enough to do two things for us:
  • Throw an exception if we try to get an isntance of SecreteMessageSender without having set the from configuration parameter.
  • Find the default implementation of the IEncoder registered in the container, and to supply that as the value for the second argument in the constructor.
So lets have a look at the application itself:

static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    SecretMessageSender sender = container.Resolve<SecretMessageSender>();

 

    sender.SendMessage("hammet", "castle is great!");

 

    Console.Read();

}


And finally our configuration:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="encoder.silly"

                service="IoC.Tutorials.Part9.IEncoder, IoC.Tutorials.Part9"

                type="IoC.Tutorials.Part9.SillyEncoder, IoC.Tutorials.Part9" />

 

      <component id="encoder.null"

                service="IoC.Tutorials.Part9.IEncoder, IoC.Tutorials.Part9"

                type="IoC.Tutorials.Part9.NullEncoder, IoC.Tutorials.Part9" />

 

      <component id="messageSender"

                type="IoC.Tutorials.Part9.SecretMessageSender, IoC.Tutorials.Part9">

        <parameters>SecretMessageSender

          <from>alex@bittercoder.com</from>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


So you can see we've registered both implementations of the encoder, with the silly encoder being first - so as mentioned in the last part - this will be the default - and we also register our message sender (with the required from parameter)... so what happens when we run it:

to: hammet
from: alex@bittercoder.com

CYSQLD IS ERDYQ!


Cool... but what if wanted to send an unencrypted message... well we have a few options:
  • Swap the order in which the implementations are registered
  • Remove / comment out any implementations we don't want (so comment out the silly encoder)
  • Or reference the implementation we specifically want to wire up to, using it's identifier...
So lets have a look at the last one...

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="encoder.silly"

                service="IoC.Tutorials.Part9.IEncoder, IoC.Tutorials.Part9"

                type="IoC.Tutorials.Part9.SillyEncoder, IoC.Tutorials.Part9" />

 

      <component id="encoder.null"

                service="IoC.Tutorials.Part9.IEncoder, IoC.Tutorials.Part9"

                type="IoC.Tutorials.Part9.NullEncoder, IoC.Tutorials.Part9" />

 

      <component id="messageSender"

                type="IoC.Tutorials.Part9.SecretMessageSender, IoC.Tutorials.Part9">

        <parameters>SecretMessageSender

          <from>alex@bittercoder.com</from>

          <encoder>${encoder.null}</encoder>

        </parameters>

      </component>

 

    </components>

  </castle>

 

</configuration>


Notice the way the parameter is formatted - instead of the markup for a property reference which starts with a hash (#) we start service references with a dollar sign ($) and then surround the components identifier with braces.

And the results of running the app now:

to: hammet
from: alex@bittercoder.com

castle is great!


And thats our first look at constructor injection... we will revisit constructor injection again in later posts, however the next part will look at setter injection.
posted @ Thursday, April 19, 2007 9:37:05 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |

8_implementations_by_key.png
So far we've looked at registering one implementation for any one service, you could call them the "default" implementation, because it's the implementation the container returns when you ask for that service... but your not limited to only having one implementation registered, and the way to do this is by giving each implementation that's registered a unique key.

There are many reasons for doing this... but in this example we'll look at one reason - because we want to vary the configuration info used...

So here's our component's code:

public class FileReader

{

    private string _fileName;

 

    public string FileName

    {

        get { return _fileName; }

        set { _fileName = value; }

    }

 

    public string ReadToEnd()

    {

        return File.ReadAllText(_fileName);

    }

}


It's a simple class which lets us read the contents of a file as many times as we like... so we're going to try registering it twice, with different configurations (and different identifiers) in the container.

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="reader.file1" type="IoC.Tutorials.Part8.FileReader, IoC.Tutorials.Part8">

        <parameters>

          <FileName>file1.txt</FileName>

        </parameters>

      </component>

      <component id="reader.file2" type="IoC.Tutorials.Part8.FileReader, IoC.Tutorials.Part8">

        <parameters>

          <FileName>file2.txt</FileName>

        </parameters>

      </component>

    </components>     

  </castle>

 

</configuration>


So far so good, lets have a look at the app itself - notice that the file1Reader and file2Reader instances are "resolved" with an extra parameter - which is the id, or key, used to select a particular implementation... but what about the default instance, which reader will that be?

static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    FileReader defaultReader = container.Resolve<FileReader>();

    FileReader file1Reader = container.Resolve<FileReader>("reader.file1");

    FileReader file2Reader = container.Resolve<FileReader>("reader.file2");

 

    Console.WriteLine("Default contents: {0}", defaultReader.ReadToEnd());

    Console.WriteLine("File1 contents: {0}", file1Reader.ReadToEnd());

    Console.WriteLine("File2 contents: {0}", file2Reader.ReadToEnd());

 

    Console.Read();

}


And here's the results of running the program:

Default contents: This is the contents of file 1.
File1 contents: This is the contents of file 1.
File2 contents: This is the contents of file 2.


So you can see that file1Reader and defaultReader are the same - and file1Reader was the first FileReader to be registered in the container -and that's the rule, the first one registered is the default... which is another example of convention over configuration with Castle, rather then having to explicity denote which is the default with some more xml noise.

Though with a little thinking you can find plenty of ways to access implementations by key to solve certain problems, for the unimaginative ... how about an application where you can provide a uri to send plain text messages to ... and depending on the scheme you need to find an implementation that can do the work of sending the message.

You have a bunch of destinations, addressed by Uri...
  • file://c:/temp/log.txt
  • ftp://ftp.google.com/log.txt
  • http://www.bittercoder.com/SimpleMessageService.aspx
  • fax://64215559555
And then you can just register the implementations/schemes you wish to support...
  • messageSender.file
  • messageSender.ftp
  • messageSender.http
  • messageSender.fax
And then look them up as required, using something like

Uri uri;

// blah blah blah

string key = "messageSender."+ uri.Scheme;

if (container.Kernel.HasComponent(key))

{

    ISender sender = container.Resolve<ISender>(key);

    // send the message at this point...

    sender.SendMessage("hi there");

}

else

{

    // no implementation registered...

    throw new NotImplementedException("no sender registered for scheme: " + uri.Scheme);

}


Personally I wouldn't do this ;o) but there's certainly no technical reason why you couldn't... notice how we check that a component is registered for that key - we could just let the container throw an exception... but then we wouldn't know how to check that a container has a certain key registered in it, would we!

The next part will be on constructor injection... and following that setter injection.
posted @ Thursday, April 19, 2007 7:23:14 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
# Wednesday, April 18, 2007

So I've decided to do a quick little series on the windsor container - all up It'll probably cover 15 to 20 posts... each one should be very short, covering some small concept... just a little nugget.

This series will be a little different then most discussions on IoC and containers... rather then get in your face with concepts like dependency injection, and encouraging testability, it's just going to focus on the container itself, and the ways you can use it... I'm not sure if it'll be of any value, but If nothing else to gets me back into blogging regularly.

The first 7 parts are already up:

I'll be posting them in batches... so the series should be finished within a week.

posted @ Wednesday, April 18, 2007 7:51:40 AM (New Zealand Standard Time, UTC+12:00)    Comments [4] | |
# Tuesday, April 17, 2007
7_switching_implementations.png
So this time we're going to look at how you can not only change configuration for a component at runtime, but actually change which component is doing the work for us... powerful stuff :)

So the "trick" here is to abstract out what features we expect our component to support from it's implementation, and stuff those into an interface... so in this case I have an idea for a simple service which lets us get the "message of the day" - so lets look at my interface:

public interface IMessageOfTheDay

{

    string GetMessageOfTheDay();

}


Now we have two implementations of this service, one that lets us have a static message set via configuration:

public class StaticMessageOfTheDay : IMessageOfTheDay

{

    private string _message;

 

    public string Message

    {

        set { _message = value; }

    }

 

    public string GetMessageOfTheDay()

    {

        return _message;

    }

}


And another, which goes to wiki quotes and grabs the quote of the day:

public class WikiQuotesMessageOfTheDay : IMessageOfTheDay

{

    public string GetMessageOfTheDay()

    {

        WebClient client = new WebClient();

        string content = client.DownloadString("http://en.wikiquote.org/wiki/Main_Page");

 

        string toFind = "<div style=\"background: #fff5f5\">";

        int start = content.IndexOf(toFind) + toFind.Length;

        int length = content.IndexOf("<a", start) - start;

 

        return content.Substring(start, length);

    }

}


so - our program is pretty simple:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    IMessageOfTheDay motd = container.Resolve<IMessageOfTheDay>();

 

    Console.WriteLine("MOTD: {0}", motd.GetMessageOfTheDay());

 

    Console.Read();

}


And so how do we swap between implementations, well we need to introduce an additional attribute to our components configuration called "service" where we specifiy what service our component implements... in this case it will be "IMessageOfTheDay" - so heres the configuration when using the Static MOTD class:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="motd.service"

                service="IoC.Tutorials.Part7.IMessageOfTheDay, IoC.Tutorials.Part7"

                type="IoC.Tutorials.Part7.StaticMessageOfTheDay, IoC.Tutorials.Part7">

        <parameters>

          <message>Welcome to my container tutorials</message>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


And running the program gives us:

MOTD: Welcome to my container tutorials

But we can now swap to a different component with the same service at run-time, and get a different implementation... here's how that looks:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

 

    <components>

      <component id="motd.service"

          service="IoC.Tutorials.Part7.IMessageOfTheDay, IoC.Tutorials.Part7"

          type="IoC.Tutorials.Part7.WikiQuotesMessageOfTheDay, IoC.Tutorials.Part7" />

    </components>

  </castle>

 

</configuration>


And now running the program gives us:

MOTD: Man is not an end but a beginning. We are at the beginning of the second week. We are children of the eighth day.

A quote from Thorton Wilder - exciting huh, this seperation between interface and implementation is what makes doing so many cool things with an Inversion of control container possible... soak up the idea.

Next time we'll take a look at getting different implementations by using their "key" - have you been wondering what the "id" attribute is for in our component definitions?? Well wonder no more.
posted @ Tuesday, April 17, 2007 11:34:46 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
6_switching_lifestyles.png
Switching lifestyles is the theme of this post... so what's that all about?

Well first off - what is a lifestyle, in basic terms it specifies how many instances will be available at any one time from the container - so at the one extreme we have components with a transient lifestyle, where any requests from those components will return new instances - and at the opposite end of the spectrum we have singleton components, where there is only one instance for the whole container - there are other types of lifestyle, but we'll leave those for another post.

So first off - castle is all about convention over configuration, and by convention a component in the container is a singleton... so in this example we'll look into ways in which you can switch a components lifestyle to being transient.

First off, heres our component:

public class AddingService

{

    private int _total = 0;

 

    public void AddAmmount(int ammount)

    {

        _total += ammount;

    }

 

    public int Total

    {

        get { return _total; }

    }

}


It lets us add stuff... how neat is that... lets see our program:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    AddingService sheepCounted = container.Resolve<AddingService>();

    AddingService catsHerded = container.Resolve<AddingService>();

 

    sheepCounted.AddAmmount(10);

    sheepCounted.AddAmmount(50);

 

    catsHerded.AddAmmount(3);

    catsHerded.AddAmmount(12);

 

    Console.WriteLine("You have counted {0} sheep and herded {1} angry cats", sheepCounted.Total,

                      catsHerded.Total);

 

    Console.Read();

}


And if we run it:

You have counted 75 sheep and herded 75 angry cats

That doesn't seem right - our service is retaining a count, so we want a fresh instance of the class every time we request it - which means we should shift our component to the "transient" lifestyle - lets have a go at doing it with configuration, by adding the lifestyle attribute to the components definition.

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="adding.service" type="IoC.Tutorials.Part6.AddingService, IoC.Tutorials.Part6" lifestyle="transient" />

    </components>

  </castle>

 

</configuration>


And now if we run it again:

You have counted 60 sheep and herded 15 angry cats

That looks a bit better... but I propose that in many cases when your writing a component you know what it's lifestyle should be, before it's ever registered in a container - for instance in this case this class should always be transient, so we can actually decorate the class with a "Transient" attribute and can skip having to put the lifestyle in the configuration, this is how that would look:

[Transient]

public class AddingService

{

    private int _total = 0;

 

    public void AddAmmount(int ammount)

    {

        _total += ammount;

    }

 

    public int Total

    {

        get { return _total; }

    }

}


There are other lifestyles available to use - it's worth having a look through the castle wiki for more details... and we'll probably cover them in another post.

In the next part we will cover switching out implementations of components themselves.

posted @ Tuesday, April 17, 2007 11:12:30 PM (New Zealand Standard Time, UTC+12:00)    Comments [2] | |

5_config_parameters.png
So in this part we're going to look at configuration parameters - parameters let you consolidate or seperate individual configuration parameters away from the components themselves, in this case we are going to create 2 config files, one for parameters to use in the live system, and the other for parameters in the debug system.

The advantage with this approach is that you don't have to duplicate the component registrations, you can leave those in one place (for the example, we just put them in the app.config)... so lets start by looking at our two sets of property configurations...
  • properties-debug.config
  • properties-live.config
properties-debug.config

<configuration>

  <properties>

    <configName>Debug</configName>

  </properties>

</configuration>


properties-live.config

<configuration>

  <properties>

    <configName>Live</configName>

  </properties>

</configuration>


And now the app.config...

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle> 

    <components>

      <include uri="file://properties-debug.config" />

      <!--<include uri="file://properties-live.config" />-->

 

      <component id="whatConfig.service" type="IoC.Tutorials.Part5.WhatConfigurationService, IoC.Tutorials.Part5">

        <parameters>

          <Configuration>#{configName}</Configuration>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


Notice how the components configuration value has a hash (#) and some braces surrounding the word "configName" - that causes castle to look up the value of the property by the same name (which we declared in the property config file).

The application code is the same as part 4.

A common approach when working with developers who may need different configurations is to <include/> a file called say properties.config that contains all the configuration values that need to change between machines, and to not check that into source control... Be sure to also keep a "master" copy of the properties, say "master-properties.config" which provides a template for developers to create their own configuration (it's not a bad place to stick the instructions for doing this as well).


posted @ Tuesday, April 17, 2007 10:30:56 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
4_switching_configs.png
So, we have all this stuff in a configuration file... but what if we have two sets of configuration we want to swap between - perhaps one for test and one for live... well here's one way of doing it with the Windsor container.

So this is our component, we use it for demonstrating which configuration is loaded:

public class WhatConfigurationService

{

    private string _configuration;

 

    public string Configuration

    {

        get { return _configuration; }

        set { _configuration = value; }

    }

}


Now here's the applications code:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    WhatConfigurationService whatConfiguration = container.Resolve<WhatConfigurationService>();

 

    Console.WriteLine("Configuration: {0}", whatConfiguration.Configuration);

 

    Console.Read();

}


So we do this by seperating our configuration sets into different files... so we create two configuration files, called:

  • container-debug.config
  • container-live.config
And here's what they look like:

container-debug.config

<configuration>

    <components>

      <component id="whatConfig.service" type="IoC.Tutorials.Part4.WhatConfigurationService, IoC.Tutorials.Part4">

        <parameters>

          <Configuration>Debug</Configuration>

        </parameters>

      </component>

    </components>

</configuration>


container-live.config

<configuration>

  <components>

    <component id="whatConfig.service" type="IoC.Tutorials.Part4.WhatConfigurationService, IoC.Tutorials.Part4">

      <parameters>

        <Configuration>Live</Configuration>

      </parameters>

    </component>

  </components>

</configuration>


So if we've moved configuration into seperate files, how does the container know about them.... well, we use includes... so here's our main configuration file now:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <!--<include uri="file://container-debug.config" />-->

    <include uri="file://container-live.config" />

  </castle>

 

</configuration>


So you can see that to shift between the debug and live configurations we just swap between including one configuration and another...

And when live is uncommented, running the program gives us this output:

Configuration: Live


There are other ways to achieve the same thing, but this is often the easiest to understand... also take careful note of that uri attribute on the include element... you don't just have to use the file:// scheme - you can include resources (embedded in your assemblies) or extend the resource subsystem with additional support for your own types of resources - but before you do, be sure to have a look at the list of out of the box possibilities here.

One question that was asked about during Architecture Camp was how container configuration could be synchronized between multiple servers, and includes provide one possibility, because you can place your shared configuration on a network share, or implement your own special resource type, that could for instance get the configuration from a webservice.

Next time we'll look at introducing configuration parameters, which is another way to deal with the problems of having to switch between configs at runtime - and can make your configuration easier to read and maintain too.

posted @ Tuesday, April 17, 2007 9:53:36 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
3_more_config_dictionaries.png

So in this part we look at creating a component which has a dictionary which gets configured... in this case we're creating a little service to handle word substitutions...

So lets have a look at the service:

public class AliasService

{

    private Dictionary<string, string> _aliases;

 

    public Dictionary<string, string> Aliases

    {

        get { return _aliases; }

        set { _aliases = value; }

    }

 

    public string Evaluate(string term)

    {

        if (_aliases == null) return term;

 

        while (_aliases.ContainsKey(term))

        {

            term = _aliases[term];

        }

 

        return term;

    }

}


And the application code that uses the service:

static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    AliasService aliasService = container.Resolve<AliasService>();

 

    string sentence = "a dog ate my homework";

 

    foreach (string word in sentence.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))

    {

        Console.Write("{0} ", aliasService.Evaluate(word));

    }

 

    Console.Read();

}


Our component is again registered without any parameters, lets run it and see what pearls of wisdom it can share:

a dog at my homework

Hmm... I'm not sure that's a great excuse for late delivery... let's do some configuration and try again:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="aliases.service" type="IoC.Tutorials.Part3.AliasService, IoC.Tutorials.Part3">

        <parameters>

          <Aliases>

            <dictionary>

              <entry key="dog">duck</entry>

              <entry key="ate">broke</entry>

              <entry key="homework">code</entry>

            </dictionary>

          </Aliases>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


So, you can see we map keys to values via an entry key... and here's the result:

a duck broke my code

You may need to tweak the mappings, depending on what you actually broke...

Now at this point you might be wondering just how the strings are getting converted into strongly typed values for the last 3 parts - and to be honest, you won't need to know most of time, just do what "seems" right and it'll probably work... but when it doesn't, check out the castle projects wiki topic on component parameters, configuration and type converters.
posted @ Tuesday, April 17, 2007 9:14:30 PM (New Zealand Standard Time, UTC+12:00)    Comments [2] | |
2_more_config_arrays.png
So welcome to part 2, today we're going to look at some more config - this time it's arrays...

So we have a class, that tells us when we can down tools and goto the beach...

public class HolidayService

{

    private DateTime[] _holidays;

 

    public DateTime[] Holidays

    {

        get

        {               

            return _holidays;

        }

        set { _holidays = value; }

    }

 

    public bool IsHoliday(DateTime date)

    {

        if (_holidays != null)

        {

            DateTime matchDate = date.Date;

            foreach (DateTime test in Holidays)

            {

                if (test.Date.Equals(matchDate))

                {

                    return true;

                }

            }

        }

 

        return false;

    }

}


We can set the days we are allowed off by adding dates to the holidays array...

So lets look at our code for running this service:

internal class Program

{

    private static void Main(string[] args)

    {

        WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

        HolidayService holidayService = container.Resolve<HolidayService>();

 

        DateTime xmas = new DateTime(2007, 12, 25);

        DateTime newYears = new DateTime(2008, 1, 1);

 

        if (holidayService.IsHoliday(xmas))

            Console.WriteLine("merry xmas!");

        else

            Console.WriteLine("xmas is only for management!");

 

        if (holidayService.IsHoliday(newYears))

            Console.WriteLine("happy new year");

        else

            Console.WriteLine("new year, you haven't done all the work for last year!");

 

        Console.Read();

    }

}


The service configuration is just like last time, we have the component registered with no parameters... so if we run the program we shall see on the screen:

xmas is only for management!
new year, you haven't done all the work for last year!

Mum will be dissapointed, she'd done a roast 'n all... so lets get some configuration in their so we can have a few days off...

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="holidays.service" type="IoC.Tutorials.Part2.HolidayService, IoC.Tutorials.Part2" >

        <parameters>

          <Holidays>

            <array>

              <item>2007-12-24</item>

              <item>2007-12-25</item>

              <item>2008-1-1</item>

            </array>

          </Holidays>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


Now let's see if we're going to have a merry xmas and a happy new year - a quick run of our application....

merry xmas!
happy new year

You don't just have to use arrays either, you can do lists too - though I didn't show them here, just use list instead of array in the xml configuration...

See you for part 3 where we do dictionary configurations.
posted @ Tuesday, April 17, 2007 8:40:16 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
1_simple_configuration.png

Welcome to part 1... today we're looking at supporting basic configuration in components without additional coding by using the windsor container.

So - with the container we can provide configuration for a component which is loaded at runtime, so every time you start your app it will be read in - you can do this using the configuration support in .Net - but using castle makes support for this very code-light in comparison... let's take a look.

So first off, we have a class we can use to calculate the tax on a gross ammount:

public class TaxCalculator

{

    private decimal _rate = 0.125m;

 

    public decimal Rate

    {

        set { _rate = value; }

        get { return _rate; }

    }

 

    public decimal CalculateTax(decimal gross)

    {

        return Math.Round(_rate*gross, 2);

    }

}


By default the tax rate is 12.5% - but we can change the tax rate by setting the "Rate" property.

Now, lets look at setting up the container... so we have this code in our sample:

private static void Main(string[] args)

{

    WindsorContainer container = new WindsorContainer(new XmlInterpreter());

 

    TaxCalculator calculator = container.Resolve<TaxCalculator>();

 

    decimal gross = 100;

    decimal tax = calculator.CalculateTax(gross);

 

    Console.WriteLine("Gross: {0}, Tax: {1}", gross, tax);

    Console.Read();

}


The windsor container is constructed with an "XmlInterpreter" - this configuration will pull the setup for our container from a section in the App.config.

Let's have a look at that:

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="taxcalc.service" type="IoC.Tutorials.Part1.TaxCalculator, IoC.Tutorials.Part1" />

    </components>

  </castle>

 

</configuration>


Running the program will display: Gross: 100, Tax: 12.50

Now, what about changing the tax rate in the configuration?

<configuration>

 

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

 

  <castle>

    <components>

      <component id="taxcalc.service" type="IoC.Tutorials.Part1.TaxCalculator, IoC.Tutorials.Part1">

        <parameters>

          <Rate>0.25</Rate>

        </parameters>

      </component>

    </components>

  </castle>

 

</configuration>


Now running the program will display: Gross: 100, Tax: 25.00

And that's part 1 done - so now you can see how can we supply configuration parameters, and provide sensible defaults for them.

Next time we'll look at configuring arrays...

posted @ Tuesday, April 17, 2007 7:16:25 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | |
Search
FeedCount

Tags...
.Net (83) .Net Reactor (4) .net user groups (9) 2008SummerRoadTrip (1) ActiveRecord (1) architecture (1) architecture chat (95) ArchitectureCamp2007 (2) asp.net (1) Astoria (1) Auckland (1) base4 (9) batching (1) binsor (1) blog (4) boo (1) books (1) C# 3.0 (9) cambodia (9) CAML.Net (1) castle (40) china (8) codecamp (3) codeplex (3) dapper.net (1) DevDefined Ltd. (4) DirectShow.Net (1) DLR (1) DSL (4) EAUG (1) Enterprise Architect (5) Enterprise Architecture (1) Enterprise Library (1) F# (1) feedburner (2) first post (1) Friendster (1) generics (1) googlegears (1) hacks (3) hardware (3) hongkong (2) Horn (1) hyper-v (1) ideas (1) IoC (21) IronPython (13) IronRuby (2) jobs (1) Languages (2) laos (8) LINQ (7) LiveId (1) LLU (1) Local Government (1) MDA (1) MDD (1) microsoft (1) Model Driven Development (1) mono (1) monorail (2) Movies (1) Music (1) nDepend (1) news (1) NHibernate (3) NUnit (2) nvelocity (1) OAuth (6) office (1) OpenSocial (1) orcon (1) photos (1) php (1) PostSharp (1) powerpoint (1) presentations (1) ReSharper (1) REST (2) rhino commons (3) rhinomocks (5) Ruby (1) SaaS (1) scm (1) Screen Architect (0) SharePoint (5) silverlight (1) Splicer (4) SQL2008 (1) supcom (1) survey (1) svn (1) Syzmk (4) thailand (6) Tools (2) Tortoise SVN (1) trac (2) Travel (36) Unity (2) vietnam (7) vista (2) visual nhibernate (1) vmware (1) volta (3) VS2008 (1) WCF (3) wiki (2) wikipedia (1) Windows Server 2008 (1) windsor (6) WinForms (1) wix (2) WPF (2) xmlrpc (1) yahoo pipes (1)
Who am I?
Alex Henderson
Alex Henderson
Auckland, New Zealand
Managing Director at Dev|Defined Limited

"Self Confessed Coding Junky for 15 years"
View Alex Henderson's profile on LinkedIn
 
Mobile: +64-21-402-969
Email: bittercoder 'at' gmail 'dot' com
MSN: bittercoder_nz@hotmail
Skype: alex.devdefined
Navigation