Windsor custom lifestyles

Windsor provides you with a pretty limited array of options when it comes to lifestyles:

  • Singleton: each time you resolve, you get the same instance. This is, for some reason, the default lifestyle
  • Transient: each time you resolve, you get a new instance. This is what I would have wanted as default 🙂
  • PerThread: it pools a singleton for each thread, so you’ll always get the same instance if you call resolve from the same thread.
  • Pooled: the documentation is not very clear about this but from the source code it seems that a pool with a given capacity is created and on each resolve one of the objects from the pool is returned. I didn’t check how which object to return is determined.
  • there’s also an undocumented PerWebRequest lifestyle and I assume it does just what it says on the tin.

Let’s say that, as it was in my case, you need a container behavior a little different than one of these: you want the container to return a different instance based on a parameter used during the type’s activation. Example:

 
IDictionary argumentsOne = new Hashtable();
argumentsOne.Add("entity", apple);
_container.Resolve<IViewModel>(argumentsOne); // a new instance 
IDictionary argumentsTwo = new Hashtable();
argumentsTwo.Add("entity", pear);
_container.Resolve<IViewModel>(argumentsTwo); // another new instance
IDictionary argumentsThree = new Hashtable();
argumentsThree.Add("entity", apple);
_container.Resolve<IViewModel>(argumentsThree); // the same instance as when called with argumentsOne

So, to get this kind of behavior from your container you need to implement your own CustomLifestyle. The easy way to do it is to subclass AbstractLifestyleManager, which provides you with some methods you can override. The interesting ones are:

  • Resolve which gets called when you try to resolve the type
  • Release which gets called when you try to release the type
  • Dispose which works as usual
  • Init, a callback invoked when your CustomLifestyle gets constructed

Obviously, Resolve should return the instance of the type, be it from your cache or from calling base.Resolve, which should get you a new one. Release should delete the right element from the cache so the next time Resolve is called a fresh instance is returned.

Here follows a sample implementation for the above scenario.

 
public class PerEntityLifestyleManager : AbstractLifestyleManager
    {
    private IDictionary<object, object> _instances = new Dictionary<object, object>();
        
    public override object Resolve(Castle.MicroKernel.CreationContext context)
    {           
        object param = context.AdditionalParameters["entity"];
        if (!_instances.Keys.Contains(param))
        {
            _instances.Add(param, base.Resolve(context));
        }
        return _instances[param];
    }

    public override bool Release(object instance)
    {
        if (_instances.Keys.Contains(instance))
        {
            _instances.Remove(instance);
            return true;
        }
        return false;
    }
}

You should then apply your lifestyle to the types you want to be resolved with it as an attribute, like this:

 
[CustomLifestyle(typeof(PerEntityLifestyleManager))]
public class MyClass : IMyInterface
{
   
}
Advertisements

Castle windsor oddities

I was at a customer today and they had a quite interesting situation to show me, and here it is.

Let’s create these dummy entities:

Entities

Entities

And now let’s register them the same way they did and see what happens when trying to resolve a Person:

result

As you can see Windsor actually “resolves” both Address and Job as if they were a dependency, setting both of them as a new instance! I don’t really think this is a bug but it’s totally not what I expected…

Having interfaces in between (so IPerson, IAddress and IJob) and then trying to resolve IPerson solves the “problem” (so I get a person with null Address and Job).