Part 12 - Decorators



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 _items = new List();

public List 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();
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:



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:




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



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

${costCalculator.default}


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





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:




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



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

${costCalculator.gstDecorator}


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

${costCalculator.default}


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





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!




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

${costCalculator.shippingDecorator}
1.20


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

${costCalculator.default}
0.0


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




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.
Read More

Part 11 - Factories



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 place within a new part of the castle configuration we haven't seen until now (so far we've only be using the section) - here's how that looks:




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


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




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




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


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



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

joe secret


type="IoC.Tutorials.Part11.ISmsService, IoC.Tutorials.Part11"
factoryId="smsService.Factory"
factoryCreate="CreateService" />





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();
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.
Read More

Part 10 - Setter Injection

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}rnfrom: {1}rnrn{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}rnfrom: {1}rnrn{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:




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




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


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


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

SecretMessageSender
alex@bittercoder.com
${encoder.null}


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

message.vm





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:



type="IoC.Tutorials.Part10.SecretMessageSender, IoC.Tutorials.Part10"> SecretMessageSender
alex@bittercoder.com
${encoder.null}
${fancyMessageFormatter}

Read More

Getting hands-on for the lazy

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:

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)

Read More