Part 7 - Switching implementations



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 = "

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

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();

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:





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




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

Welcome to my container tutorials






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:




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



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




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

Part 6 - Switching between lifestyles



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 catsHerded = container.Resolve();

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.




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








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

Part 5 - Configuration parameters

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

      Debug
 


properties-live.config



    Live


And now the app.config...



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





#{configName}





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 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).

Read More

Part 4 - Switching configurations



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();

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



Debug






container-live.config



Live






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:




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







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

Part 3 - Dictionary configuration

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 _aliases;

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

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:




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





duck
broke
code








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