WindsorContainer specifying Lifestyle programmatically

On a project I've been using Castle's IOC Container.  On the other recent projects I've been using Unity for IOC.  One difference between Unity and Windsor is the default lifestyle (or in Unity LifetimeManager).  On the UnityContainer if you do not specify a LifetimeManager then the lifetime is transient (this means that for each call to Resolve a new instance of your type will be returned).  When using the Windsor container the default lifestyle is Singleton (which means that for each call to Resolve the same instance of the type is returned).  I guess it's a matter of preference what you want to happen here.  My opinion is that if it's a singleton and you don't know it's a singleton you could get some very hard to track down bugs (concurrency issues, state management problems etc).  If you know it's a singleton and you want it to be a singleton then that's fine.  Therefore, I prefer to make everything transient by default and you have to ask for it to be a singleton (not sure what others think but that's my thought).  Another reason is that I want other people more used to the Unity container to get transient by default (I'm not sure what Structure Map and the others do?).

So there are two requirements here, the first is by default use a transient lifestyle and the second is to be able to specify the lifestyle when registering a type (adding a component to use Windsor's term).

You can do this in two ways out of the box, in the XML configuration or by attributing your classes (see here for more info).  I'm not doing either, I'm configuring my container in code (I prefer configuring my container in code because it's refactor friendly - i.e. when I rename my interface or class I don't have to remember to go and update my XML configuration, also, it's quicker to type!).

In the Unity world when you register a component you can specify the lifetime manager you want to use - there isn't a way (I can see) to do the same with Castle.  But castle is extensible so I extended it to meet my need.

In my project I've hidden the IOC container behind my own interface, this helped me no end when I came to do this as my Container Configuration class just had an IIocContainer to work with):

public class ContainerConfiguration
{
  private readonly IIocContainer container;
 
  public ContainerConfiguration(IIocContainer container)
  {
     this.container = container;
  }
 
  public void Configure()
  {
     container.Register<IAuthenticationService, FormsAuthenticationService>();
     ....
  }

My implementation for the Castle container now uses my implementation of IContributeComponentModelConstruction to specify the lifestyle when I register the type (by default it registers it with a Transient lifestyle and there's an override that let's you specify the one you want):

public class MyProjectsContainer : IIocContainer
{
   private readonly IWindsorContainer container;
   private readonly LifestyleResolver lifestyleResolver = new LifestyleResolver();
 
   public PBRCastleWindsorContainer(IWindsorContainer container)
   {
      if (container == null) throw new ArgumentNullException("container");
      this.container = container;
      this.container.Kernel.ComponentModelBuilder.AddContributor(lifestyleResolver);
   }
 
   public void Register<T, U>()
      where U : class
   {
      lifestyleResolver.SetLifestyle(typeof(U), LifestyleType.Transient);
      container.AddComponent<T, U>();
   }
.....

For completes the IContributeComponentModelConstruction implementation:

public class LifestyleResolver : IContributeComponentModelConstruction
{
  private readonly Dictionary<Type, LifestyleType> configuration = new Dictionary<Type, LifestyleType>();
 
  public void ProcessModel(IKernel kernel, ComponentModel model)
  {
     LifestyleType lifestyleType;
     if (configuration.TryGetValue(model.Implementation, out lifestyleType))
     {
        model.LifestyleType = lifestyleType;
     }
  }
 
  public void SetLifestyle(Type type, LifestyleType lifestyleType)
  {
     configuration.Add(type, lifestyleType);
  }
}

Again, hope this helps and if anyone knows a better way let me know!

Comments

# re: WindsorContainer specifying Lifestyle programmatically
Gravatar Hi Tom,

Nice post. I was just Googling for StructureMap and it's support for PerWebRequest Lifestyle (something that Windsor supports out of the box and which I've created a Unity LifetimeManager for) and this article popped up! :)

Instead of writing your own IoC container wrapper you might want to consider using the 'CommonServiceLocator' as it has a bunch of service locator adapters out of the box.

http://www.codeplex.com/CommonServiceLocator

Cheers,

Mike

PS - I still need to organize that curry at somepoint ;)
Left by Michael Taylor on 8/19/2009 8:41 PM
# re: WindsorContainer specifying Lifestyle programmatically
Gravatar Hi Mike,

Thanks for the feedback - I'll check out the common service locator. Tom Quinn was telling me about a standardised interface for IOC but I was too lazy to go looking for it :)

I'm using the built in Web Request Lifestyle that comes with Windsor, seems to work well. We wrote our own HttpRequest Lifetime manager for a previous project when we used Unity as our container - that worked well too.

I'm free whenever for a curry! :)

Cheers,

Tom
Left by TPeplow on 8/20/2009 12:15 AM
# re: WindsorContainer specifying Lifestyle programmatically
Gravatar Hi Tom,
I think this may be what you were looking for ;-)
devlicio.us/.../...ifestyle-in-castle-windsor.aspx
Left by Tom Quinn on 9/13/2009 11:43 PM

Leave Your Comment

Title*
Name*
Email (never displayed)
 (will show your gravatar)
Url
Comment*

Please add 5 and 6 and type the answer here:

Preview Your Comment.