3

I have a solution which has the following projects:

  • Core (contains classes for processing, not related to business objects / domain)
  • Domain (contains business objects)
  • Harness (console app)
  • MVC4 app
  • Persistence (contains implementations of repository interfaces, EF mappings, etc)
  • Repositories (contains repository interface)
  • Tests (contains unit tests)

I would like to use NInject as my IoC container as I have experience with it however I am open to suggestions for something that would better suit my needs.

The domain objects need to know about the repository so they can do data access (i.e. the Person class might want to retrieve all AddressDetails). Everything is coded to interfaces to help with mocks in unit testing.

I don't want the domain project taking on a dependence on an IoC container but I need some way of having all instances created in the domain project getting the right repositories injected. How can I do this? I also want to be able to do injections from the harness and test project where necessary. The only way I can think of doing this is by having a static object in the Domain class which wraps the StandardKernel from NInject and call that to populate the dependencies. It would be nice also if i can have constructor injection working which I don't think it would using that method. The other alternative I can think of is have a factory which builds the domain objects with the correct dependencies, but I'd rather be able to have IPerson person = new Person() rather than have to call a factory each time.

Thanks in advance.

Sam
  • 4,219
  • 7
  • 52
  • 80
  • Maybe this helps: Introduce an abstraction (= Layer SuperType) and hide Ninject in behind. For production code implement a class which uses Ninject. For unit testing you can use some other implementation (maybe a Mocking framework). The implementation of the Layer SuperType can be placed somewhere else than the Domain project. This way you will get rid from the dependency between Domain project and Ninject. – Theo Lenndorff Aug 25 '12 at 05:48
  • Just spent quite some time trying to find the dups of this - there were 3. They are now all indexed from http://stackoverflow.com/questions/1475575/where-should-i-do-dependency-injection-with-ninject-2 . VTCing this as Dup, sorry! – Ruben Bartelink Aug 25 '12 at 07:15

2 Answers2

3

The domain objects need to know about the repository so they can do data access (i.e. the Person class might want to retrieve all AddressDetails). Everything is coded to interfaces to help with mocks in unit testing.

Domain objects is in-memory object and persistent ignorance, so it does not need to know any repositories. AddressDetails should be lazy-loading if you use ORM, or, it should be assigned outside Person entity.

So, with this way, needless to put domain entities into IoC container. Please note that, don't over-use IoC Container, think about which types should be put in it. If everything is put into IoC Container, it would be messy type pool.

Appropriate classes which should be put into IoC are the main classes in each layers, ex:

  1. Services.
  2. Repository.
  3. ORM.
  4. Controllers.
  5. Cross-cutting concerns: Log, Cache...

Other in-memory classes should not put in.

cuongle
  • 74,024
  • 28
  • 151
  • 206
  • The domain objects know about the repository interfaces in this project. This is so, for example an action can be recorded against an object. The domain objects contain business logic and therefore need to be able to interact with one and other. – Sam Aug 25 '12 at 09:49
1

Sounds like you should introduce Composition Root into MVC4 project and console application. Thus all dependencies will be coupled only there for whole production code. Also you may define your own implementation of StandardKernel, or use autodiscovery to find all implementations.

There is two examples how to implement composition root with overload of StandartKernel and autodiscovery at ninject.web.mvc that could be useful as starting point. Composition root for console application usually has trivial implementation.

For test project you could use ninject.mockingkernel with appopriate mocking library, or build all dependencies yourself. Second option should be obvious for pure unittesting, but for integration tests first one is more appopriate.

Injection of domain objects

  • First there are several well know injection method:

    • via constructor,
    • property,
    • method
    • context.

    For example, implement only one not default constructor for domain object, that defines all required dependencies for that object. If it depends on repository, specify this in constuctor of domain object, and there is no other way to create this particular domain object without specifing it.

  • Second, by doing so you could avoid dependency on any dependency injection library
Akim
  • 8,469
  • 2
  • 31
  • 49
  • This doesn't answer the question about how to inject into domain objects. – Steven Aug 25 '12 at 09:42
  • First there are several _well know_ injection method: via constructor, property, method and context. For example, implement only one not default constructor for domain object, that defines all required dependencies for that object. If it depends on repository, specify this in constuctor of domain object, and there is no other way to create this particular domain object without specifing it. Second, by doing so you could avoid dependency on any dependency injection library – Akim Aug 25 '12 at 09:59
  • I'm going to go with your answer as reading up on the composition root ultimately led me to work out my problem. I have completely avoided requiring a service locator pattern and all controllers are having their dependencies injected automatically, which are then passed to the domain layer when instantiating objects. – Sam Sep 04 '12 at 23:38