Julian Jelfs’ Blog

Detecting possible lifestyle conflicts in the Windsor container

Posted in Castle by julianjelfs on April 28, 2009

When using the Castle Windsor container you have to make decisions about the lifestyles of your components. The common options are Singleton (which is the default) and Transient. If you are using the container within a web application you are likely to also want to use the PerWebRequest lifestyle.

When you have a complex object graph with lots of dependencies problems can arise if you have inadvertently given one or more components the wrong lifestyle. Generally speaking it is most likely to cause problems if a component has a dependent component which has a shorter lifestyle than the component it is a dependent of.

Let’s think of a concrete example using the following two classes:

public class UserContext
{
    public int SessionId {get;set;}
}

public class DoStuffService
{
    public DoStuffService(UserContext context)
    {
        ....
    }
}

In this case the UserContext class contains some information that pertains to the context in which the code is executing, namely the session id. For this reason we rightly want use the PerWebRequest lifestyle for this component (I’m not going to worry about how this component gets it’s SessionId property populated – that’s not the point).

Now, what is less obvious is that this decision implies that the DoStuffService must also have a lifestyle with a duration less than or equal to UserContext. Consider the following container configuration:

new WindsorContainer()
    .Register(
         Component.For<UserContext>().LifeStyle.PerWebRequest,
         Component.For<DoStuffService>()
        );

This is perfectly valid and you will get no complaints from the container, but what it means is that only one instance of the DoStuffService will be created by the container since the lifestyle defaults to Singleton. When it is constructed for the first and only time, we will get an instance of the UserContext injected in correctly. However, the next web request will expect a new instance of UserContext but it will not get one. i.e. UserContext has effectively become a Singleton as well.

If you are lucky, your code will fail. But the really nasty thing is that in a single user environment e.g. a development environment, Singleton and PerWebRequest can behave in exactly the same way so that you never notice a problem. Furthermore, the problem is unlikely to be as obvious as it is in this example with a much more complicated object graph.

You can see that this is not really something that the container can prevent in any generic way because there is no real way to tell whether it will in practice cause a problem. However, it is possible for us as users to decide on a policy and then to validate that the configured container conforms to that policy. A good policy seems to be that a component cannot have a lifestyle that is longer in duration than any of  it’s dependent components. Such a policy can be implemented as follows:

public static void ValidateLifestyles(this IWindsorContainer container)
{
    var errors = new ContainerLifeStyleException();
    var comparer = new LifeStyleComparer();

    foreach (var node in container.Kernel.GraphNodes)
    {
        var component = (ComponentModel)node;
        foreach (var dependent in node.Dependents)
        {
            var dependentComponent = (ComponentModel)dependent;
            if (comparer.Compare(component.LifestyleType, dependentComponent.LifestyleType) > 0)
                errors.Add(component, dependentComponent);
        }
    }

    if (errors.ContainsErrors)
        throw errors;
}

ContainerLifeStyleException is just a collection of all of the problems found along the way and LifeStyleComparer is just an implementation of IComparer<LifestyleType> so that you can decide which lifestyles are of longer duration than others .

You can then call this extension method immediately after configuring your container and any potential lifestyle problems will be reported.

Advertisements
Tagged with:

Interceptor Selection with Castle Windsor

Posted in Castle by julianjelfs on March 27, 2009

As you may know it is possible to do some nice AOP type stuff by adding interceptors to objects served up using the Windsor container. It is also possible to inject interceptors on the fly using the interceptor selector extension point. I’m not going to talk about how that is done because that is very well described here.

I wanted to describe something that I thought was not obvious about the implemenation on this feature. I had assumed that if I returned false from IModelInterceptorSelectors.HasInterceptors then IModelInterceptorSelectors.SelectInterceptors would not be called. However, this is not the case. If the component already has interceptors, then IModelInterceptorSelectors.SelectInterceptors will be called regardless of what you return from IModelInterceptorSelectors.HasInterceptors.

This means that you really need to put your conditional logic to decide whether to dynamically inject interceptors into both interface implementations if there is any chance that the components already have interceptors.

This seems a bit wrong to me …. ?

A further gotcha is that the following approach for injecting an interceptor before other interceptors does not seem to work:

public InterceptorReference[] SelectInterceptors(ComponentModel model)

{

model.Interceptors.AddFirst(InterceptorReference.ForType<MethodProfilingInterceptor>());

return model.Interceptors.ToArray();

}

because it throws an exception in the CopyTo method of the InterceptorsCollection. I found that the approach in the linked article above does work fine though (presumably because it does not involve converting the Interceptor reference collection to an array).

Tagged with: