8

I've read in several sources including Mark Seemann's 'Ploeh' blog about how the appropriate placement of the composition root of an IoC container is as close as possible to the entry point of an application.

In the .NET world, these applications seem to be commonly thought of as Web projects, WPF projects, console applications, things with a typical UI (read: not library projects).

Is it really going against this sage advice to place the composition root at the entry point of a library project, when it represents the logical entry point of a group of library projects, and the client of a project group such as this is someone else's work, whose author can't or won't add the composition root to their project (a UI project or yet another library project, even)?

I'm familiar with Ninject as an IoC container implementation, but I imagine many others work the same way in that they can scan for a module containing all the necessary binding configurations. This means I could put a binding module in its own library project to compile with my main library project's output, and if the client wanted to change the configuration (an unlikely scenario in my case), they could drop in a replacement dll to replace the library with the binding module.

This seems to avoid the most common clients having to deal with dependency injection and composition roots at all, and would make for the cleanest API for the library project group.

Yet this seems to fly in the face of conventional wisdom on the issue. Is it just that most of the advice out there makes the assumption that the developer has some coordination with the development of the UI project(s) as well, rather than my case, in which I'm just developing libraries for others to use?

4 Answers 4

2

Your binding module approach is the best solution. If the client is unlikely to change the configuration, the use of DI is questionable, for your library specifically.

If you wish to create a library for release to the public, you probably don't want clients to deal with the complexity or rigidity of the particular DI system you favor at the moment. Libraries are best when they are lower level components that can be used without lots of dependencies, or extensive training. Any DI system you select will change over time, and may become incompatible with client applications.

2

A library is supposed to be a black box with a clean domain-specific API. There's no problem with using any tools or patterns you need inside a library, including DI, as long as it does not leak to the client and constrain him in some way.

If there's a need to provide extensibility or library configuration changes, it still can be done without sharing a single composition root between the library and the client.

Whether you can justify your library depending on another 3rd party library just to implement DI in your library, is a different issue, but keep in mind that the DI pattern itself can be implemented without any dependencies.

-1

If you are developing libraries (not applications) for others to use, than you should still implement dependency injection. For me the term "Dependency injection" is just a set of practices that lead to a better separation of concerns and loose coupling. This is what makes your library well structured and easily testable (most of the time).

With regards to the IoC container, I don't see any harm in having IoC container in the library project. Somewhere you will have a composition root (an entry point) into your library so to me it makes perfect sense to wire up your dependencies in the composition root. How you do it is entirely up to you.

As an example, I have recently used a library for capturing signatures and a library for scanning bar codes. Both of them were simple interop libraries (COM wrappers). Each library required me to initialise it before I could do anything. For example:

var isReady = _signatureCapture.Initialise()
if (isReady)
{
   // Do stuff
}

Bar code scanning library was very similar:

_scanner.Initialise();
_scanner.OnScan += OnScanHandler;

I have been using both libraries and I have no idea whether they use IoC container or not. However I do know that the entry points into the library are in the Initialise methods. I'm guessing that all the dependencies are wired up in the Initialise method, which serves as a composition root.

If you are worried about relying on a third party IoC container, than you can roll with your own, much simplified implementation. Developers often worry about library becoming obsolete or superseded by something better, but in reality I have not yet seen a project where the team decided to swap out one IoC container for the other.

1
  • 4
    Libraries should avoid unnecessary dependencies. Except in the case of a very complex library, that is more like an application, most library users will not want a dependency on a particular DI implementation. Commented May 1, 2014 at 3:14
-2

The beauty of external libraries is that they should do what ever it is they say they would do, while exposing a simple, straight forward interface. How ever complex it actually is to do it, should not be the business of the developer who implements it. If DI actually makes the work of the API developer less complex, then it makes 100% sense to use it, as long as it is used properly and its module is declared at the entry point of the API. In developing an MVC app recently, I abstracted the data layer using a repository pattern and even further abstracted by placing a service layer in between the MVC app a the repository layer, both been Class Library projects. I had an ICache Interface mapped to a Cache Class for my Service Context. I initially implemented it using MVC.Web.Cache, but on a later Iteration I swapped it for System.runtime.cache and you can only imagine how large the scale of that Refactor would have been with out my utilizing DI. So my advice; "Go for it".

1
  • this post is rather hard to read (wall of text). Would you mind editing it into a better shape?
    – gnat
    Commented Sep 2, 2014 at 3:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.