The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Windsor and component instance lifetimes

Posted by Davy Brion on May 1st, 2008

In my previous Windsor post i showed you how you can use the Windsor container to manage your components and their dependencies. Since it was merely an introductory post on Windsor, i only showed how you can use it to handle dependencies. But there’s a lot more you can do with it, and that you should know about.

One thing you’ll definitely need to know to properly use Windsor, is that of component instance lifetimes. After all, you want the container to manage your components and their dependencies. But there’s more to the management of components than merely filling in dependencies. Should the container return a new instance of a component? Should it return an already existing instance? How do you control that behavior without having clients know about it? After all, should clients of components really know about that? Is that not an implementation detail that might be better of being properly encapsulated from clients?

Windsor allows you to register components with specific lifestyles. These are the lifestyles you can use:

  • Singleton: components are instantiated once, and shared between all clients
  • Transient: components are created on demand
  • PerWebRequest: components are created once per Http Request
  • Thread: components have a unique instance per thread
  • Pooled: Optimization of transient components that keeps instance in a pool instead of always creating them
  • Custom: allows you to specify a custom lifestyle… you’d have to specify a type that implements the ILifeStyleManager interface

The Singleton lifestyle is actually the default. I’m not so happy with that being the default, but oh well… If we continue with our previous sample, we can verify that Singleton is indeed the default lifestyle for a registered component. Suppose the component is registered like this:

            _container.AddComponent<IOrderRepository, OrderRepository>();

Then the following test would pass:

            var r1 = Container.Resolve<IOrderRepository>();

            var r2 = Container.Resolve<IOrderRepository>();

 

            Assert.That(ReferenceEquals(r1, r2));

But if we change the registration to this:

            _container.AddComponentWithLifestyle<IOrderRepository, OrderRepository>(LifestyleType.Transient);

Then the test obviously fails because both requests to get an IOrderRepository instance will create a new OrderRepository instance.

You might be wondering what happens when you define a component as a singleton, but one of its dependencies is transient:

            _container.AddComponentWithLifestyle<IOrderDataAccessor, OrderDataAccessor>(LifestyleType.Transient);

            _container.AddComponentWithLifestyle<IOrderRepository, OrderRepository>(LifestyleType.Singleton);

The answer is pretty straightforward: when you request an instance of type IOrderRepository the first time, it will create a new IOrderAccessor instance as well and pass it to the OrderRepository constructor. The second time you request an instance of type IOrderRepository, the container already has the singleton instance cached, so a new IOrderAccessor instance is not created.

If you really want this behavior (a new IOrderDataAccessor instance whenever the singleton IOrderRepository is requested) you can get it working pretty easily. Right now, our OrderRepository implementation uses Constructor Injection:

        private IOrderDataAccessor _accessor;

 

        public OrderRepository(IOrderDataAccessor accessor)

        {

            _accessor = accessor;

        }

If we add Setter Injection as well the container will use the setter injector when we request the IOrderRepository instance after it has already been created:

        public IOrderDataAccessor DataAccessor

        {

            set { _accessor = value; }

        }

Because we have both Constructor Injection and Setter Injection, the container will supply a new IOrderDataAccessor when the OrderRepository instance is created. And when it is requested again after its creation, the container will supply a new IOrderDataAccessor instance to the OrderRepository using the setter of the dependency.

It’s nice to know that this is possible, but i wouldn’t recommend this approach… It’s very confusing and would certainly cause problems in multi-threaded scenarios. You’re better off injecting an IOrderDataAccessorFactory object when the repository is created, and then let the repository request a new IOrderDataAccessor instance to be used locally whenever it’s needed (as in: as a local variable during method execution, but certainly not as a field of the class).

There’s also the other way around of course… suppose the dependency is configured as a singleton, and the component to be used is configured to have the Transient lifestyle. The singleton dependency will only be created once, and every time you request a transient component that is dependent on a singleton component, the container injects the singleton instance in the transient component.

By now, I hope you realize that an Inversion Of Control Container is about more than merely Dependency Injection and increasing testability. There’s most certainly a lot more to it than that :) . I have a few more posts coming up about how using an IoC container can make your life as a developer easier.

One Response to “Windsor and component instance lifetimes”

  1. Jozef Sevcik Says:

    Thanks for lifestyles explanation, this should be a part of Castle documentation.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>