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

 

Extend Unity and UnityContainer with Extension Methods in C# 3.0


For the most part, I think Dependency Injection and Inversion of Control in the .NET Developer Community is becoming more and more a commodity. A year ago there were big differences between the various frameworks, but the gap has narrowed such that for most applications any DI framework will do.

The various depenendency injection frameworks, like:

roughly provide the same services in terms of dependency injection. Sure they have their strengths and weaknesses and subtle differences on how they choose the appropriate constructor for injection, but mainly the big differences are in how you register types in the container and extra services offered by the container. Most of the differences in containers can be narrowed even further using the extensibility of the containers and by adding other functionality using C# 3.0 Language Features like Extension Methods.

Many of the containers come with useful type registration methods that are built into their fluent interface; included in their modules, registries, or extensions; and/or are available separately in a contrib project via extension methods. Lately a lot of the StructureMap 2.5 posts have been about these simple, yet useful registration features, and others like Autofac, for example, were built from the ground up to leverage fluent interfaces and the new C# 3.0 language features.

Unity from Microsoft Patterns & Practices doesn't have a lot of these extra convenient registration methods yet, but we can certainly create some using extension methods. We can create extension methods that work with IUnityContainer or UnityContainer that offer richer type registration methods. You can also create Unity Extensions to do the same thing. ( Note: Enterprise Library 4.0 ships with custom unity extensions to register the various application block types into UnityContainer ).

 

Extending Unity using Extension Methods for UnityContainer or IUnityContainer

Below is an example of an extension method for IUnityContainer, called RegisterSingleton, that will loop through all types in the current assembly looking for classes that implement a specific interface. Any classes that begin with "Default" in its name are assumed to be the default instance, and others will be registered as named instances using the type name. All of them use the ContainerControlledLifetimeManager to provide singleton lifetime management.

This is meant to be a simple example on extending Unity with extension methods and is not intended to be useful as is :) However, you can use this sample as a stepping stone for creating your own extension methods that work properly according to your coding standards and needs.

 

using System;

using System.Reflection;

using Microsoft.Practices.Unity;

 

namespace UnityExtensionExample

{

    class Program

    {

        static void Main(string[] args)

        {

            IUnityContainer container = new UnityContainer();

 

            // Call Our Extension Method

            container.RegisterSingleton<ILogger>();

 

            // Retrieve the default and named instances

            ILogger defaultLogger = container.Resolve<ILogger>();

            ILogger logger1 = container.Resolve<ILogger>("Logger1");

            ILogger logger2 = container.Resolve<ILogger>("Logger2");

 

            // Make sure it worked.

            defaultLogger.Write("Hello");

            logger1.Write("Hello");

            logger2.Write("Hello");

        }

    }

 

    public static class UnityContainerExtensions

    {

        public static void RegisterSingleton<T>(this IUnityContainer container) where T : class

        {

            foreach (var type in Assembly.GetExecutingAssembly().GetTypes())

            {

                if (!typeof(T).IsAssignableFrom(type) || type.IsInterface)

                    continue;

 

                if (type.Name.StartsWith("Default"))

                    container.RegisterType(typeof(T), type, new ContainerControlledLifetimeManager());

                else

                    container.RegisterType(typeof(T), type, type.Name, new ContainerControlledLifetimeManager());

 

            }

        }

    }

 

    public interface ILogger

    {

        void Write(string message);

    }

 

    public class DefaultLogger : ILogger

    {

        public void Write(string message)

        {

            Console.Write(string.Format("DefaultLogger: {0}", message));

        }

    }

 

    public class Logger1 : ILogger

    {

        public void Write(string message)

        {

            Console.Write(string.Format("Logger1: {0}", message));

        }

    }

 

    public class Logger2 : ILogger

    {

        public void Write(string message)

        {

            Console.Write(string.Format("Logger2: {0}", message));

        }

    }

}

 

 

Hopefully the code above is pretty straight forward.

I suspect that if there aren't some already, you will see extensions like these in the Unity Contrib Project:

 

Feel free to check out other Unity Tutorials and Unity Screencasts.

If you are looking for books on C# 3.0 to better understand C# 3.0 Language Features and Extension Methods, you can check out a couple of my reviews:

 

You can also check out my C# 3.0 Tutorials.

Hope this helps.


Tags: DependencyInjection, IoC, Unity


RSS Syndication RSS Syndication

Twitter Microsoft .NET Web Developer Follow me on Twitter

Google+ Microsoft .NET Web Developer Follow me on Google+


Topics



 

Recent Links