Click here to Skip to main content
15,893,668 members
Articles / Programming Languages / C#

Cleanup Your Unity Configuration Code

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
17 Apr 2013CPOL2 min read 12.9K   9   5
How to utilize an interface and extension method to cleanup your Unity type registration code.

Introduction 

CodeProject and its community are a great resource that I have used for a number of years now. With this article (my first) I will attempt to give something back.

Background 

I have been using Unity for awhile, and it has always bothered me to have a method for type registration that could be really long.

Example of long registration method:  

C#
public IUnityContainer InitializeContainer()
{
    var Container = new UnityContainer();

    Container.RegisterType(typeof(IResolver<>), typeof(UnityResolver<>));
    Container.RegisterType(typeof(IEventResolver<>), typeof(EventResolver<>));
    Container.RegisterType<IEnrollmentRepository, EnrollmentRepository>();
    Container.RegisterType<IFaqRepository, FaqRepository>();
    Container.RegisterType<IHousingUnitRepository, HousingUnitRepository>();
    Container.RegisterType<IInformationRepository, InformationRepository>();
    Container.RegisterType<INoteRepository, NoteRepository>();
    Container.RegisterType<IProgramRepository, ProgramRepository>();
    Container.RegisterType<IScratchPaperRepository, ScratchPaperRepository>();
    Container.RegisterType<IStatusRepository, StatusRepository>();
    Container.RegisterType<ISoftwareRepository, SoftwareRespository>();
    Container.RegisterType<IStudentRepository, StudentRepository>();
    Container.RegisterType<ITestRepository, TestRepository>();
    Container.RegisterType<IDialogService, DialogService>();
    Container.RegisterType<IFaqService, FaqService>();
    Container.RegisterType<IEnrollmentService, EnrollmentService>();
    Container.RegisterType<IInformationService, InformationService>();
    Container.RegisterType<IJsepService, JsepService>();
    Container.RegisterType<INoteService, NoteService>();
    Container.RegisterType<ISettingsService, SettingsService>();
    Container.RegisterType<IScratchPaperService, ScratchPaperService>();
    Container.RegisterType<ISoftwareService, SoftwareService>();
    Container.RegisterType<IStudentService, StudentService>();
    Container.RegisterType<ITestService, TestService>();
    Container.RegisterType<ILookupService, LookupService>();
    Container.RegisterType<IReportService, ReportService>();
    Container.RegisterType<IDbContext, StudentTrakkerContext>();
    Container.RegisterType<IUnitOfWork, UnitOfWork>();

    return container;
} 

This method could be refactored to use the fluent interface, thus making it a little easier to read.

C#
public IUnityContainer InitializeContainer()
{
    var Container = new UnityContainer();

    Container.RegisterType(typeof(IResolver<>), typeof(UnityResolver<>))
             .RegisterType(typeof(IEventResolver<>), typeof(EventResolver<>))
             .RegisterType<IEnrollmentRepository, EnrollmentRepository>()
             .RegisterType<IFaqRepository, FaqRepository>()
             .RegisterType<IHousingUnitRepository, HousingUnitRepository>()
             .RegisterType<IInformationRepository, InformationRepository>()
             .RegisterType<INoteRepository, NoteRepository>()
             .RegisterType<IProgramRepository, ProgramRepository>()
             .RegisterType<IScratchPaperRepository, ScratchPaperRepository>()
             .RegisterType<IStatusRepository, StatusRepository>()
             .RegisterType<ISoftwareRepository, SoftwareRespository>()
             .RegisterType<IStudentRepository, StudentRepository>()
             .RegisterType<ITestRepository, TestRepository>()
             .RegisterType<IDialogService, DialogService>()
             .RegisterType<IFaqService, FaqService>()
             .RegisterType<IEnrollmentService, EnrollmentService>()
             .RegisterType<IInformationService, InformationService>()
             .RegisterType<IJsepService, JsepService>()
             .RegisterType<INoteService, NoteService>()
             .RegisterType<ISettingsService, SettingsService>()
             .RegisterType<IScratchPaperService, ScratchPaperService>()
             .RegisterType<ISoftwareService, SoftwareService>()
             .RegisterType<IStudentService, StudentService>()
             .RegisterType<ITestService, TestService>()
             .RegisterType<ILookupService, LookupService>()
             .RegisterType<IReportService, ReportService>()
             .RegisterType<IDbContext, StudentTrakkerContext>()
             .RegisterType<IUnitOfWork, UnitOfWork>();

    return container;
}

The method above is a little cleaner, but to my eye could still use some work, so lets refactor to the following:

C#
public IUnityContainer InitializeContainer()
{
    var container = new UnityContainer();

    container.RegisterModule<PersistenceModule>()
             .RegisterModule<ServiceModule>();

    return container;
}

Neat and concise like code should be.

Using the code

In order to achieve the above cleanliness, we will create an interface IUnityConfigurationModule, a couple classes that implement said interface, and the RegisterModule extension method.

First off is the interface:

IUnityConfigurationModule.cs:

C#
// IUnityConfigurationModule.cs

using Microsoft.Practices.Unity;

namespace Champion.Core.Interfaces
{
    public interface IUnityConfigurationModule
    {
        void Configure(IUnityContainer contatiner);
    }
} 

The IUnityConfigurationModule interface contains a contract of one method: Configure. The Configure method is where our type registrations will occur.

PersistenceModule.cs:
C#
// PersistenceModule.cs

using Champion.Core.Interfaces;
using Champion.Core.Persistence;
using Microsoft.Practices.Unity;

namespace Champion.Core.Persistence
{
    public class PersistenceModule : IUnityConfigurationModule
    {
        public void Configure(IUnityContainer container)
        {
            container.RegisterType<IDbContext, ToyServiceCenterContext>()
                     .RegisterType<IUnitOfWork, UnitOfWork>()
                     .RegisterType<IAnnouncementRepository, AnnouncementRepository>()
                     .RegisterType<IEnrollmentRepository, EnrollmentRepository>()
                     .RegisterType<IFaqRepository, FaqRepository>()
                     .RegisterType<IHousingUnitRepository, HousingUnitRepository>()
                     .RegisterType<IInformationRepository, InformationRepository>()
                     .RegisterType<INoteRepository, NoteRepository>()
                     .RegisterType<IProgramRepository, ProgramRepository>()
                     .RegisterType<IScratchPaperRepository, ScratchPaperRepository>()
                     .RegisterType<IStatusRepository, StatusRepository>()
                     .RegisterType<ISoftwareRepository, SoftwareRespository>()
                     .RegisterType<IStudentRepository, StudentRepository>()
                     .RegisterType<ITestRepository, TestRepository>();
        }
    }
}
ServiceModule.cs:
C#
// ServiceModule.cs

using Champion.Core.Interfaces;
using Champion.Core.Services;
using Microsoft.Practices.Unity;

namespace Champion.Core.Services
{
    public class ServiceModule : IUnityConfigurationModule
    {
        public void Configure(IUnityContainer container)
        {
            container.RegisterType<IDialogService, DialogService>()
                     .RegisterType<IFaqService, FaqService>()
                     .RegisterType<IEnrollmentService, EnrollmentService>()
                     .RegisterType<IInformationService, InformationService>()
                     .RegisterType<IJsepService, JsepService>()
                     .RegisterType<INoteService, NoteService>()
                     .RegisterType<ISettingsService, SettingsService>()
                     .RegisterType<IScratchPaperService, ScratchPaperService>()
                     .RegisterType<ISoftwareService, SoftwareService>()
                     .RegisterType<IStudentService, StudentService>()
                     .RegisterType<ITestService, TestService>()
                     .RegisterType<ILookupService, LookupService>()
                     .RegisterType<IReportService, ReportService>();
        }
    }
}

Now that we have our configuration modules complete. It is time for the RegisterModule extension method that brings it all together. 

UnityExtensions.cs:

C#
// UnityExtensions.cs

using Champion.Core.Interfaces;
using Microsoft.Practices.Unity;

namespace Champion.Core.Extensions
{
    public static class UnityExtensions
    {
        public static IUnityContainer RegisterModule(this IUnityContainer container, IUnityConfigurationModule module)
        {
            if (module != null)
            {
                module.Configure(container);
            }
            return container;
        }

        public static IUnityContainer RegisterModule<T>(this IUnityContainer container) where T : class, IUnityConfiguratiModule, new()
        {
            T module = new T();
            module.Configure(container);
            return container;
        }

    }
}

You'll notice two methods here. The first one, you use by passing in an instance of a class that implements IUnityConfigurationModule

Example of first method:

C#
container.RegisterModule(new PersistenceModule());

Then we have the second method that uses generics to provide a cleaner implementation.

Example of second method:

C#
container.RegisterModule<PersistenceModule>();

So there we have it. My take on cleaning up type registration code.  

Points of Interest

Inspiration for this article came from Rusell East's Blog, and his IModule implementation.

I usually create the module class inside the individual assemblies where the types being registered reside. This of course will require those particular assemblies to have a reference to Unity. If that is something you would prefer to avoid you could always have the module classes reside in your main project and add references to the required assemblies. 

Conclusion  

Creating this article has been an eye-opener for me into how difficult it is to write an article. Kudos to all you prolific writers.

I look forward to your comments, suggestions, rants, etc.

History 

  • 4/15/13 - Initial post.
  • 4/16/13 - Cleaned up the code examples to make them more readable, and in one instance believable.
  • 4/17/13 - My perfectionist side is coming out. More cleanup.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
CarelAgain7-Sep-13 19:49
professionalCarelAgain7-Sep-13 19:49 
GeneralRe: My vote of 5 Pin
John Holzer19-Sep-13 4:32
professionalJohn Holzer19-Sep-13 4:32 
QuestionOne request Pin
Tridip Bhattacharjee17-Apr-13 4:13
professionalTridip Bhattacharjee17-Apr-13 4:13 
QuestionNice! Pin
Brisingr Aerowing15-Apr-13 12:04
professionalBrisingr Aerowing15-Apr-13 12:04 
AnswerRe: Nice! Pin
John Holzer16-Apr-13 3:44
professionalJohn Holzer16-Apr-13 3:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.