2

I'm using the Unity IoC framework and have a Bootstrapper.cs class in my host MVC layer to register all components. However in my architecture I have a 'services' layer below the MVC layer, that too uses DI and there are repository interfaces injected into it (repository interfaces are not used in the MVC layer - it has the services layer Interface injected into its Controllers).

So my question is the following: can I still register the repository interface to it's concrete type in the MVC/UI layer for the entire app, or do I add another reference to Unity and create another Bootstrapper.cs class in my 'services' layer to define Interface types for that that specific layer uses?

Even if the answer is I can register the Interface in the UI layer, I'd still like to know the common practice too. The thing I don't like about registering that type in the MVC/UI layer is I would have to add a reference to the Repository layer just to make the registration, even know it is not used in that layer. It's used in the services layer.

Thanks!

atconway
  • 18,827
  • 24
  • 140
  • 216
  • 1
    If you do that in the UI, it mean you have to reference the service implementation in the UI, which I think you dont want to do that. Also when you want to do integration test between the service and the repository layer, you need the DI registered, so if you do that in the UI , how can your integration test would work? – Dan Hunex Jan 24 '13 at 22:15

4 Answers4

6

Each application should have its own Composition Root, the place where you configure the application (see this answer for details).

It depends on the context, but generally speaking, if you split your container configuration among the layers you are going to make decisions about the configuration of your layers too close to the layers and you'are likely to lose the general view.

For example, in one of your business logic layers you'are registering a service:

container.RegisterType<ISercice1, MyImplementation1>(new PerThreadLifetime())

But when using that layer in a web application you could decide that a PerSession or PerRequest lifetime would be better lifetimes. This decisions should be in only one place and not spread through the layers.

Community
  • 1
  • 1
onof
  • 16,589
  • 7
  • 46
  • 82
3

I turn your question on its head.

If you add a reference to Unity in your class libraries, you would have added dependencies to the framework you are using. That is quite the opposite of what you are trying to achieve.

The only adaptation your classes should need is to support constructors or using public properties - on interfaces. That's it!

So your application entry point should do all the 'bootstrapping'. Note that a entry point could be different applications, as well as different test projects. They could have different configurations and mocking scenarios.

If your bootstrap.cs gets large, you could split it up into smaller parts for readability reasons. But I reject the idea of classes having any knowledge about the fact that they are being bootstrapped/moqed/injected and by what.

Consider re-use. Your current libraries is using Unity. They may be used in a project using StructureMap. Or why not Ninject.

2

In short, yes it is possible to keep the configuration at the top of the process or localized to each module. However, all dependencies must be resolved for the entire object graph in the process.

Localizing the configuration by keeping it in each module (assembly) is often a good idea because you are allowing your service layer to take responsibility for its own configuration. My answer to this question, IMHO, is a good practice.

Community
  • 1
  • 1
Davin Tryon
  • 62,665
  • 13
  • 135
  • 126
  • Thanks - I looked at your answer in the link and I didn't quite get it 100% (not your fault). Do you know of any extended examples that could help me with this? – atconway Jan 24 '13 at 22:26
  • I'm not sure of an extended example. What are the things that your are unsure of? – Davin Tryon Jan 24 '13 at 22:37
  • Actually I read a few more examples and get it now. There is still just a single Composition Root though correct? It's just the installers dictate the dependencies specific for that layer correct? – atconway Jan 25 '13 at 15:10
  • Yes, the composition root must be the entry point (object) for the call. And this must be resolved in order to then map the object graph below it. – Davin Tryon Jan 25 '13 at 15:53
  • Any ideas since that example was using Windsor and I'm using Unity on the deviation for creating the Installer classes? – atconway Jan 25 '13 at 16:44
0

Yes, application should have one composition root at entry point. But it can be a good practice to keep registrations of a classes inside a layer where they are implemented. Then pull these registrations from layers at composition root, registering implementations layer by layer. This is why:

  1. Registration within layer can be redefined in other place, for example at entry point. Most of IoC libraries work in such a way that registration done later erases the registration done earlier. So registration within layer defines just a default behavior which can be easily overridden.
  2. You don't need to reference IoC library in all your projects\layers, even if you have registrations defined inside these layers. A very simple set of wrapper classes will allow you to abstract away from IoC specifics anywhere except your entry point.
  3. When your application has several entry points, reusable registration will greatly help to prevent repeating the same registration. This copy\paste is always bad. And applications have several entry points quite often. For example, consider the scenario of cross-platform application having a separate entry point for every platform it targets. Or business logic reused in web site and in background process.
  4. With reusable registration, you can build a very effective testing system. You will be able to run a whole layer from tests, mock whole layers in automated way, and do it very effectively, minimizing efforts on writing tests.

See my blog article illustrating these points in more detail, with a working sample.

avitenberg
  • 1,501
  • 16
  • 16