4

My project is organized as follows

  • ASP.NET MVC 3 WebApp
  • Domain.Core - Interfaces [library]
  • Domain.Core.Entity - Entities [library]
  • Infrastructure.Core - Implementation of Interfaces [library]
  • Infrastructure.IoC - Uses Unity as a means of achieving Inversion of Control [library]

The predicament is as follows:

If I were to add a generic method to an interface in my Domain.Core, such as the following, I get a compile error that asks me to add a reference to Domain.Core.Entity in the Infrastructure.IoC project.

T Get<T>(int Id) where T : EntityBase, new();

T can be a class EntityBase or Blog which inherits from EntityBase or a few other entities that all inherit from EntityBase. The idea is to return an entity based on what child class is provided so that the child class is loaded with the default data that is required for all classes that implement EntityBase.

So, the question is two fold:

  1. Is it better to not reference the Domain.Core.Entity project in the IoC project and keep things clean?

  2. How would I achieve something like the above without having to muddy the cleanliness of references?

Thank you.

Note: I went through a few of the questions here to search for this topic but didn't see any. If you do see it, then let me know and I will delete this question.

AboutDev
  • 1,923
  • 1
  • 23
  • 33

2 Answers2

4

With Dependency Injection, it's best to have a single component with the responsibility of composing all the various collaborators. This is the third party in Nat Pryce's concept of Third-Party Connect, or what I call the Composition Root. In the architecture outlined above, this responsibility seems to fall on Infrastructure.IoC, so given this structure, there's nothing wrong with adding a reference from Infrastructure.IoC to Domain.Core.Entity - in fact, I would find it more surprising if it were not so.

However, as an overall bit of feedback, I think it's worth considering what benefit is actually being derived from having a separate Infrastructure.IoC library. The entry point of that application (the ASP.NET MVC application) will need to have a reference to Infrastructure.IoC, which again must have a reference to all libraries in order to compose them. Thus, the ASP.NET MVC application ends up having an indirect reference to all other libraries, and you might as well merge those two.

(Technically, you can decouple the various libraries by relying on some sort of late binding mechanism such as XML configuration or Convention over Configuration, but the conceptual responsibility of Infrastructure.IoC is going to remain the same.)

For more information, you may want to read this answer: Ioc/DI - Why do I have to reference all layers/assemblies in entry application?

Community
  • 1
  • 1
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Thanks for the info. I used a pattern that is as follows: MVC references Domain.Core, Domain.Core.Entity and Infrastructure.IoC. Domain.Core references Domain.Core.Entity. Domain.Core.Entity doesn't reference any other library. Infrastructure.Core references Domain.Core and Domain.Core.Entity. Infrastructure.IoC references Domain.Core and Infrastructure.Core. This allows the MVC app to only reference minimally what is needed. Having a separate IoC library allows us to replace the Infrastructure.Core at will. At least that was the hope. – AboutDev Apr 23 '12 at 16:48
  • 2
    [continued.]I think I have overly complicated the architecture of this system trying to make it extensible. I really need to go through Marks' book (which I bought a few months ago) to learn more about how IoC/DI should be done. – AboutDev Apr 23 '12 at 16:49
3

Why split the Domain.Core from Domain.Core.Entity? And why split Infrastructure.Core from Infrastructure.IoC?

I think you can get away with a 3 project structure:

  1. Domain - has no dependencies on the other 2 projects. May contain entities and interfaces.
  2. Infrastructure - contains interface implementations and the Unity container. Depends only on Domain project.
  3. MVC - depends on both Domain and Infrastructure.

If you are worried about programming against concrete classes instead of interfaces, give the classes in the Infrastructure project a different namespace. You should then only have to use that namespace maybe a couple of times (in Global.asax or bootstrapper) if at all.

This way it is very clear what projects depend on what. Since you are using unity, this is a form of onion architecture. If you find later that you should split Infrastructure or Domain out into more than 1 project, you can refactor.

IMO, dependencies only get muddy or unclean when you have references like System.Web.Mvc or Microsoft.Practices.Unity in your domain project(s). Like Mark says in his answer, the outer layers of your "onion" will have dependencies on the inner layers, there's not much you can do to avoid that. But try to make the domain concentrate on its core business, avoiding as much detail of how it will be used in a UI as possible.

danludwig
  • 46,965
  • 25
  • 159
  • 237
  • The more I look at the onion architecture, the more it makes sense. What are the negative aspects of it? – AboutDev Apr 23 '12 at 16:50
  • One negative aspect could be performance, but that comes from the IoC container (some are faster than others). Also it might not be appropriate for the application depending on the business needs (can be overkill for quickly prototyping an app for example). IMO it has many more strengths than weaknesses. – danludwig Apr 23 '12 at 18:44