Part 13 - Injecting Service Arrays

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:




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



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

1.20



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

0.0



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


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



${calc.total}
${calc.shipping}
${calc.gst}







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

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