Jason
Jason

Reputation: 2721

Should I abstract the configuration of an IOC container away from the UI?

Our team has been building a DDD app that has a strongly defined application service layer that is built as the "API" of the system. It handles pulling everything together from the domain and infrastructure to accomplish generic tasks. It uses nothing but DTOs as input/output so the domain is never exposed beyond this layer.

Now we want to add a dependency injection container into the mix and we are faced with some tough choices. We have two client applications that use the application services to do their work: an MVC 2 app and a windows service app. Traditionally all the configuration code to make dependency injection work is put in the global.asax file in the mvc project, which I have seen numerous examples of. The problem is that IOC registration code is then duplicated in the windows service and modified slightly for that platform.

The problem I have is that DI requires the client app to know what to register and how, which also requires the client app to have references to the domain and infrastructure layers. The whole idea with having an app services layer was that it was the only thing clients should know and talk to. My proposed solution was to create a "Dependency Service" in my app service layer that clients would call once, and it would configure the DI container since it knows what is required. It would also have methods to allow the client app to register additional dependencies of its own. For example the MVC project would register its controller factory, and the windows service would register its startup class. I wanted to know if this is uncommon or if I am on the wrong path with this idea. Has anyone else come across this issue before?

Upvotes: 0

Views: 549

Answers (2)

Nicholas Blumhardt
Nicholas Blumhardt

Reputation: 31857

There are many ways to skin a cat; it seems like you're taking the wrong approach however. The entry point of the application (Global.asax or Program.cs) should absolutely be the place that selects the components to be configured in the IoC container. Your services, on the other hand, generally shouldn't have any IoC configuration knowledge embedded in them. My guess is you're already following this principle but are reexamining it because of the repetitive configuration.

To make this feasible without code repetition, as you've described, many IoC containers provide modularisation constructs that encapsulate the configuration of a set of related components. In Autofac (and Ninject IIRC) these are called 'modules' - http://code.google.com/p/autofac/wiki/StructuringWithModules. Castle Windsor calls them 'installers' while StructureMap calls them 'registries'.

By factoring configuration into modules, the amount of configuration code in the application startup method is reduced. In your example, as a simplification, you may create three modules:

  • CoreModule
  • WebModule
  • ServiceProcessModule

The CoreModule would contain configuration for the components that are shared and behave identically in each of the execution environments.

WebModule and ServiceProcessModule would contain registrations for components specific to those environments, plus specialised configuration of any shared components that are configured differently depending on the host.

Your web app startup would then be something like:

foo.RegisterModule<CoreModule>();
foo.RegisterModule<WebModule>();
// Resolve root component, run app

While the service process would be very similar but substituting WebModule for ServiceProcessModule.

This style of configuration will scale much better to many application entry points and/or many subsystems of components, when compared with the static initialisation method with conditional code.

Hope this helps. Nick

Upvotes: 3

Mariusz
Mariusz

Reputation: 1409

I put a configuration class into my DDD or DomainModel project and call the configuration class in the UI.

public static class IoCConfigurator()
{
    public static void Initialize()
    {
        // your code here
    }
}

In your UI you have to call only the Initialize() method and thats all. You can use it in your MVC Global.asax and even in your windows service app as well. No code duplication.

Works very well for me.

Upvotes: 2

Related Questions