Handling Multitenancy with Castle Windsor – Part 1

At my new job, we have an e-commerce app. It’s your typical online shop. Unlike most though, it is for specific commercial customers to use, each of which has their own business rules and our app tries to cater for it. Unfortunately, it doesn’t do a great job of this. Thinking about it, multi-tenant applications seem like a hard problem to solve without resorting to lots of “if-else” tests, etc. but that’s where tools like Castle Windsor really shine.

If you’re familiar with IoC (inversion of control) containers in general, you’ll understand how they resolve dependencies for you to build an object graph ready to use. Of course, Windsor does this too but it also provides some interfaces that help us control that resolving behaviour. Specifically, I’m talking about the IHandlerSelector interface.

IHandlerSelector allows you to plug-in to the resolving process and provide a means to influence which implementation of your registered interface should be returned by Windsor. As an example, imagine your service layer contains some kind of controller. By providing an implementation of IHandlerSelector that knows about the controller’s interface you could check the role of the logged in user and if applicable return an admin version of the controller otherwise return the ordinary and more restricted controller, all of which requires no conditional checks in the calling code. Or how about a controller with a method, say, PlaceOrder(). Maybe there are different rules to consider when CompanyA is logged in and calls PlaceOrder() compared to when CompanyB is logged in. All we have to do is provide an implementation of IHandlerSelector that determines the company that is logged in and return the appropriate controller. Yes, you need two (or more) implementations of the controller but at least we’re conforming to the Open/Closed principle and thus reducing the bloat that the alternative of one fat controller gives us not to mention the increased risk of bugs every time we have to go in and change it.

So what does an implementation look like?

Here’s our controller interface:

public interface IOrderController
{
    void PlaceOrder();
}

Let’s say we have two implementations (not shown here but not hard to imagine), one for each customer that do things differently when placing orders.

How does Windsor know which one to instantiate at the point it tries to resolve our object graph? Like this:

public class OrderControllerHandlerSelector : IHandlerSelector
{
    public bool HasOpinionAbout(string key, Type service)
    {
        return service == typeof(IOrderController);
    }

    public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
    {
        var user = HttpContext.Current.User;

        if(user.IsInRole("SomeRoleThatIdentifiesCompanyA"))
            return handlers.Where(x => x.ComponentModel
               .Implementation == typeof (CompanyAController)).First();

        return handlers.Where(x => x.ComponentModel
               .Implementation == typeof(CompanyBController)).First();
    }
}

The implemenation is trivial. The HasOpinionAbout method tells Windsor that this class is interested in deciding which IOrderController to return, whilst the SelectHandler method makes the actual decision.

Now all we have to do is register our class with the container:

WindsorContainer _container = new WindsorContainer();
_container.Kernel.AddHandlerSelector(new OrderControllerHandlerSelector());

In my opinion, this is a great way to keep our code clean and nicely separated. If we gain a new customer and things are slightly different for that customer too, all we need do is provide a new IOrderController implementation and update our OrderControllerHandlerSelector class meaning we never have to touch our other implementations. OCP for the win!

About these ads

One thought on “Handling Multitenancy with Castle Windsor – Part 1

  1. Pingback: Handling Multitenancy with Castle Windsor – Part 2 (Domain Events) « Eventually Consistent

Comments are closed.