Click here to Skip to main content
11,574,494 members (54,788 online)
Click here to Skip to main content

Cleanup Your Unity Configuration Code

, 17 Apr 2013 CPOL 6.1K 9
Rate this:
Please Sign up or sign in to vote.
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:  

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.

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:

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:

// 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:
// 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:
// 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:

// 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:

container.RegisterModule(new PersistenceModule());

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

Example of second method:

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)

Share

About the Author

John Holzer
Software Developer
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
CarelAgain7-Sep-13 19:49
memberCarelAgain7-Sep-13 19:49 
GeneralRe: My vote of 5 Pin
John Holzer19-Sep-13 4:32
memberJohn Holzer19-Sep-13 4:32 
QuestionOne request Pin
Tridip Bhattacharjee17-Apr-13 4:13
memberTridip Bhattacharjee17-Apr-13 4:13 
hi, can u please provide source code to download. i never work with unity in production but like to know where lines of statement gone found generally in config file.

u did not specify any statement in config file so how this is working. how far i know person has to write class/assembly related info in unity . how did u manage to work with config entry? please share the knowledge. thanks
tbhattacharjee

QuestionNice! Pin
Brisingr Aerowing15-Apr-13 12:04
professionalBrisingr Aerowing15-Apr-13 12:04 
AnswerRe: Nice! Pin
John Holzer16-Apr-13 3:44
memberJohn Holzer16-Apr-13 3:44 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150624.2 | Last Updated 17 Apr 2013
Article Copyright 2013 by John Holzer
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid