Question

I had a similar question a while back, but with much less of a grasp of the whole IoC/DI topic and as well as what I was aiming to achieve, so here goes again....

I am building a library for common use within our company. The most commonly used parts of the public API are already IoC friendly, but in the lower level areas, there's still quite some newing up going on, which I'd like to get rid of (though at this time more for formal reasons than real necessity).

This in itself will be easy enough to do, but then of course everytime the library is being used, all the components have to be wired up again. As this will pretty much always look the same, I'd normally just wrap those default registrations in an Autofac module and be done with it.

(Here's question 1: Would this module go in the main library assembly or should it be a standalone package, even if Autofac would likely be the only IoC container being used with the library?)

Now the problem is that I am currently the only developer in the company that really sees the purpose of IoC or knows what an IoC container does at all, let alone how it is used, and it would be a bad idea to tell everyone else they can either use the Autofac package or just build a graph of a dozen+ objects manually using poor man's DI. (I know the guys - they would just leave it alone and build what they need themselves, because I'm crazy anyway with all my many tiny classes.)

What I thought about to solve this is adding something like a Service Locator from which to pull preconfigured objects for the commonly needed types (which would look the same as those wired up by the Autofac module), maybe wired up internally by a lightweight IoC container.

I know that Service Locator is an antipattern and which kinds of problems it creates, and I'd never use it as the (my) means of object composition, but as a "shortcut" for the IoC/SOLID impaired, would it be feasible? What other options would I have? Might it even make sense in that case to include the Autofac module with the library and just have the "Service Locator" act as a frontend to it?

Was it helpful?

Solution

For a framework, different rules hold than for line of business applications. This holds, in my opinion, also when applying dependency injection. You see this when looking at the design of the Microsoft Patterns & Practices Enterprise Library. It is completely designed around the dependency injection pattern, but normal users will not know this. It uses factories to make the user's life easier. In your case, it is not wise to force other developers to use dependency injection, since this will probably only annoy them, since you are doing things that just seems making things harder, and they won't see the benefit of it. This will probably give them a negative feeling with the whole DI thing, and you will lose to possibility to introduce them with DI later on (because they will already made up their mind in disliking it).

Would this module go in the main library assembly or should it be a standalone package

I would normally not integrate this in the library itself, since from a architectural perspective, you simply don't want your library to depend on any DI container. However, when you take a look at the Enterprise Library, you will see that it takes a hard dependency on the Unity DI framework. You can change EntLib to use a different container, but the EntLib still references Unity. This allowed the framework designers to supply the user with convenient factory methods, and it allows the framework to be used, without having to call some sort of 'Framework.Bootstrap` method in your application.

Do your best to design your framework with the SOLID principles in mind, because you know this is simply the best thing to do. It also allows you to show case this way of designing applications in the future (and might interest others in dependency injection). But as a framework designer, you have to think about who your users are and come up with an API that works well for them. Keeping the Framework Design Guidelines for .NET in mind can help lot for instance.

When looking at Enterprise Library, you see that the root/main types have a factory. Everything else is resolved for you under the covers. I think this is the way to go. Don’t bother your users with an API where they need to wire everything up themselves, especially for the normal/simple use cases.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top