views:

41

answers:

3

Lets say I have an ASP.NET MVC web application which consists lots of assemblies. Here's a very simple example:

  • MyApp.Web
    • the web app
  • MyApp.Services
    • contains interfaces and implementations of domain services, e.g. IOrderProcessor, DefaultOrderProcessor
  • MyApp.DAL
    • contains interfaces and implementations of repositories, e.g. IOrderRepository, SqlOrderRepository

The web app will initialize the IoC container during startup (e.g. register controllers, etc.). I'm not sure whose responsibility it should be to register the domain services and repositories.

What I have done now, is to create a static class in each assembly, each containing a method responsible to register the types contained in the assembly. E.g. for the DAL assembly:

namespace MyApp.DAL
{
  public static class AssemblyInitialization
  {
    public static void RegisterTypes(IUnityContainer container)
    {
      var lm = new TransientLifestyleManager();
      container.RegisterType<IOrderRepository, SqlOrderRepository>(lm);
      ...
    }
  }
}

These methods are then called by the web app during startup (in a unit-test project I would of course not be able to use these methods, but would have to register all test-implementations inside the test-project).

I'm not sure if this is a good practice. For example this solution ties the two assemblies to a specific IoC container (Unity in the sample shown above). This seems to be a possible anti-pattern (similar to using the service-locator pattern).

Therefore I'm looking for your opinions about how this should be handled, e.g:

  • should all registration stuff be handled by the main app (the web app)?
  • or would this put too much knowledge about the contents of the separate (self-contained) assemblies into the main app?
  • should I abstract the specific IoC container using a self-made interface?
  • other things to consider?
+1  A: 

It is always the responsiblity of the entry point in which case here is your MyApp.Web. This normally "goes into/called from" your glabal.asax.

Aliostad
+1  A: 

Start "bootstrapping" in you entry point. However, you can delegate the registrations to each loaded assembly by using a class implementing IRegistration in those assemblies.

This is pretty much what you're doing right now. But, in stead of using static classes, you can find the IRegistration implementations through reflection on initialize.

Since you're using MVC, take a look at Turbine, which does a fine job at this. Or better yet, use it in your application :)

Bertvan
What is IRegistration, where is it defined? Couldn't find it anywhere. If this is something from a specific IoC container, then I guess it will not be much of an improvement over my current solution.
M4N
Bertvan
Well, and you'd still need to look for those implementations yourself, obviously. But seriously, take a look at MVC Turbine, it does (amongst other things) exactly that in an ASP.NET MVC environment.
Bertvan
A: 

IMHO, your code should defer making this choice as long as possible--till the last responsible moment. I use Unity, so I can wait until web.config is loaded to declare what types I wish to inject.

I believe that if you aren't using a configuration file to do this you're doing something wrong. The purpose of using a DI framework is to reduce and/or remove these compile-time dependencies.

Will