skip to the main content area of this page
Patterns and Practices

 

Generic Decorator Chains Example using Unity Dependency Injection Container


Unity v1.2 has support for AOP with the addition of the Interception Extension and 3 new interceptors: TransparentProxyInterceptor, VirtualMethodInterceptor, and InterfaceInterceptor. Anytime you start talking about AOP you inevitably start talking about the Decorator Pattern, which is the fundamental design pattern that serves as the basis of AOP. Discussion of the decorator pattern may then lead to the discussion of Generic Decorator Chains, which is now supported in Unity v1.2 as well.

 

Generic Decorator Chains Using Unity Dependency Injection Container

Decorators are very valuable for adding functionality to a class without modifying the class. Typically you see decorators being used to inject cross-cutting concerns such as logging, validation, authorization, and other such concerns.

Decorators help us achieve adherence to fundamental design principles, such as the Single-Responsibility Principle ( SRP ) and the Open-Closed Principle ( OCP ).

Leveraging generics in C# 3.0 or VB 9.0 further simplifies the use of the decorator pattern so that we don't have to create decorators for each specific type.

The example shown below shows an example of injecting validation around a generic repository interface, IRepository<T>, in the domain model. In this case we create a generic decorator, ValidatingRepositoryDecorator<T>, that does the validation on the entity instance before passing it to the repository if it is valid. If the entity is invalid, typically a validation exception is thrown and the entity never gets passed to the repository.

This sample is void of any validation and persistence code as it is immaterial to understanding the pattern. The code is as follows:

 

using Microsoft.Practices.Unity;

 

namespace GenericDecoratorChains

{

    class Program

    {

        static void Main(string[] args)

        {

            IUnityContainer container = new UnityContainer();

            container.RegisterType(typeof (IRepository<>), typeof (Repository<>), "Repository");

            container.RegisterType(typeof (IRepository<>), typeof (ValidatingRepositoryDecorator<>),

                                   new InjectionConstructor(new ResolvedParameter(typeof(IRepository<>), "Repository")));

 

            var repository = container.Resolve<IRepository<string>>();

            repository.Add("David Hayden");

        }

    }

 

    public interface IRepository<T>

    {

        void Add(T instance);

    }

 

    public class Repository<T> : IRepository<T>

    {

        public void Add(T instance)

        {

            // Do Something

        }

    }

 

    public class ValidatingRepositoryDecorator<T> : IRepository<T>

    {

        private readonly IRepository<T> _inner;

 

        public ValidatingRepositoryDecorator(IRepository<T> inner)

        {

            _inner = inner;

        }

 

        public void Add(T instance)

        {

            // Validate - If invalid, throw exception

 

            _inner.Add(instance);

        }

    }

}

 

In this example the ValidatingRepositoryDecorator becomes the default instance of IRepository<T> in the UnityContainer. Repository<T> becomes a named instance in the UnityContainer and specified as the service that is to be injected into the constructor of the ValidatingRepositoryDecorator.

Using this configuration, validation will occur first and then if valid, pass the entity to the repository as expected. Notice the end user is none the wiser that we have used generic decorator chains to create the functionality. From a maintainability perspective, however, we have broken up the responsibility in discrete pieces, allowing us to remove and change functionality easily within the application.

 

Conclusion

Hopefully this helps one understand the use of generic decorator chains using the Unity Application Block. Check out other Unity Tutorials and Unity Screencasts for more information.

 

Hope this helps,

David Hayden


Tags: DependencyInjection, IoC, Unity