Chain of Responsibility Design Pattern and Unity Dependency Injection Container

 

by David Hayden

Tags: Unity Tutorials, Unity Screencasts, Unity on .NET Rocks!

 

I received an email asking how to use patterns & practices Unity Dependency Injection Container to configure a set of handlers for the Chain of Responsibility Design Pattern.

 

 

Chain of Responsibility Design Pattern

I don't plan on going into the chain of responsibility pattern in detail. A quick definition is as follows -

“Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.”

Rather than having the client determine who or what should handle a particular operation, you can just connect the handlers in a chain and have them decide if they want to handle the operation or pass it to the next in the chain.

 

 

Registering the Handlers via Unity IoC Container

Many of the examples on the Chain of Responsibility Pattern show the client manually adding and connecting the various handlers in a chain, but that is more for illustration purposes. Ideally, you will add these handlers to your dependency injection container of choice so the client is not even aware of the fact that the Chain of Responsibility Pattern is being used. I'll show this using Unity, but of course you can use Castle Windsor, StructureMap, Spring.NET, Autofac, Ninject, etc.

Let's pretend we need a way to process various payments, Credit Card Payment, Check Payment, and Cash Payment:

 

public abstract class Payment{}

 

public class CreditCardPayment : Payment {}

 

public class CheckPayment : Payment {}

 

public class CashPayment : Payment {}

 

We can define a generic interface for a payment handler to be used to handle the various payments:

 

public interface IHandler<T> where T: class

{

    IHandler<T> Successor { get; set; }

    void ProcessRequest(T instance);

}

 

Now we can go ahead and create various payment handlers for each payment:

 

public class CreditCardPaymentHandler : IHandler<Payment>

{

    public IHandler<Payment> Successor { get; set; }

 

    public void ProcessRequest(Payment instance)

    {

        if (instance.GetType() == typeof(CreditCardPayment))

        {

            // Do Something

        }

        else if (Successor != null)

            Successor.ProcessRequest(instance);

    }

}

 

public class CheckPaymentHandler : IHandler<Payment>

{

    public IHandler<Payment> Successor { get; set; }

 

    public void ProcessRequest(Payment instance)

    {

        if (instance.GetType() == typeof(CheckPayment))

        {

            // Do Something

        }

        else if (Successor != null)

            Successor.ProcessRequest(instance);

    }

}

 

public class CashPaymentHandler : IHandler<Payment>

{

    public IHandler<Payment> Successor { get; set; }

 

    public void ProcessRequest(Payment instance)

    {

        if (instance.GetType() == typeof(CashPayment))

        {

            // Do Something

        }

        else if (Successor != null)

            Successor.ProcessRequest(instance);

    }

}

 

Register the various payment handlers with the Unity Dependency Injection Container:

 

IUnityContainer container = new UnityContainer();

 

// Credit Card Payment Handler

container.RegisterType(typeof (IHandler<Payment>),

    typeof (CreditCardPaymentHandler),

    new InjectionProperty("Successor",

    new ResolvedParameter(typeof (IHandler<Payment>),

        "CheckPaymentHandler")));

 

// Check Payment Handler

container.RegisterType(typeof(IHandler<Payment>),

    typeof(CheckPaymentHandler), "CheckPaymentHandler",

    new InjectionProperty("Successor",

    new ResolvedParameter(typeof(IHandler<Payment>),

        "CashPaymentHandler")));

 

// Cash Payment Handler

container.RegisterType(typeof(IHandler<Payment>),

    typeof(CashPaymentHandler),"CashPaymentHandler");

 

As you will notice, we have registered the various payment handlers in a chain : CreditCardPaymentHandler -> CheckPaymentHandler -> CashPaymentHandler.

In the client portion of your application you can just ask for IHandler<Payment> to be injected when necessary and the client neither has to create the chain, know the chain of responsibility is being used, nor know which handlers are being used and what they are being used for. This gives us wonderful loose coupling in the application and the ability to maintain the application better. Here I am using a service locator approach for illustration, but you want to inject the dependency into the client:

 

// Get Payment Handler

var handler = container.Resolve<IHandler<Payment>>();

 

// Handle Cash Payment

handler.ProcessRequest(new CashPayment());

 

 

Conclusion

Hopefully this helps one better understand how to connect these chains using Unity. Here I chose using the interface, but you can also use a configuration file and read the handlers in the configuration. Check out my example on Generic Decorator Chains as well:

 

posted on Wednesday, November 19, 2008 11:47 AM

Main

News

Green Tea

.NET Development

Enterprise Library

Patterns & Practices