views:

69

answers:

2

I’m new to Dependency Injection and had a question/need guidance.

I had an application that used the repository pattern for data access. I used StructureMap to get the correct repository and all worked well.

I have since broken out my model (including the repository logic) into its own assembly and added a service layer. In the interest of DI the service layer class takes an IRepository in its constructor. This seems wrong to me as now all consumers of my model need to know about the repository (at least configure their DI to know which one to use). I feel like that is getting into the guts of the model.

What sounds wrong with this?

A: 

I understand your dilemma there Dan, I too spent lots of time wrestling over that in my mind. I believe the way I decided to go forward with was one of best ways to encapsulate all of the concerns and still have easily maintainable loosely coupled objects.

I wrote this blog post specifically about NHiberante but if you look at the repository pattern in implement you can easily change the NH specific code to use your backingstore.

Creating a common generic and extensible NHiberate Repository

Chris Marisic
A: 

An application written to use dependency injection typically configures a single container instance where all the interface/implementation type mappings have been registered at an initialization stage of the application. This would include the registration of the repositories, services, and any consumers of the service within the application.

By resolving the consumers of the service through the container, consumers need only indicate their dependency upon the service, not any dependencies the service might need. Therefore, the consumers of the service will not be coupled to its dependencies (e.g. your repository). This is the benefit of doing dependency injection through a container as opposed to doing manual dependency injection.

If you are designing services to be consumed by other applications in the form of a reusable library then your options will vary depending on the level of flexibility you wish to offer.

If you presume all clients of your library will be using dependency injection, then you will need to provide an appropriate amount of documentation about what types need to be registered within their container.

If you presume all clients will be using a specific container (e.g. StructureMap), then you can ease the registration requirements by providing registries which encapsulate all the specific registration needs for the client.

If you wish to allow your library to be used by clients not using their own dependency injection container then you can provide a static factory which returns the service. Depending on the level of complexity, such a scenario may not require use of a container (for example, if your service is comprised by just a few objects in all). If your library is comprised of a substantial amount of components which need to be composed then you might have factories which resolve the services through their own shared internal infrastructure initialization needs.

Derek Greer