Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IoC in class library. Where to bootstrap

I'm using a class library that can be reused by other components. In this class library I'm using unity for dependency injection. For this class library I create a test project. The caller also gets a test project. One thing I'm uncertain about is the location of the bindings. Should I incorporate this in the class library or should I do this from the calling application?

like image 258
Patrick Avatar asked Apr 17 '12 12:04

Patrick


People also ask

How do IoC containers work?

The IoC container creates an object of the specified class and also injects all the dependency objects through a constructor, a property or a method at run time and disposes it at the appropriate time. This is done so that we don't have to create and manage objects manually.

Should I use IoC container?

The most valuable benefit of using an IoC container is that you can have a configuration switch in one place which lets you change between, say, test mode and production mode. For example, suppose you have two versions of your database access classes...

What is the use of IoC container in C#?

IoC means that one code calls another; DI goes beyond that and implements IoC by using composition. A DI or IoC container needs to instantiate objects (dependencies) and provide them to the application. To do so, it must deal with constructor injection, setter injection, and interface injection.


2 Answers

I know that an answer has been chosen, however I think a part of Unity is being overlooked. Since this was a specific Unity question I thought I point out the UnityContainerExtension base class that implements the IUnityContainerExtensionConfigurator. This is there for API library to extend to make it easy for the entry-point application who owns the Container to have an easy way to make sure your library gets registered with the Container correctly, and allows the API owner control of what gets registered and how.

This is used by the Microsoft Enterprise Libraries for this purpose.

I am going to use a Logging library as a simple:

public class LoggingUnityExtension : UnityContainerExtension {     protected override void Initialize()     {         Container.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());     } } 

Then the entry-point application does this:

public class Bootstrapper : UnityBootstrapper {     protected override void ConfigureContainer()     {         base.ConfigureContainer();          Container.AddNewExtension<EnterpriseLibraryCoreExtension>();         Container.AddNewExtension<LoggingUnityExtension>();         // ...      }      // ... } 

Now they have registered Enterprise Library and the API for the Logging library. It's very simple for the entry-point application with this method which is what any library developer should have as a goal.

like image 81
Rodney S. Foley Avatar answered Sep 28 '22 20:09

Rodney S. Foley


This is an interesting problem. How can you dependency inject re-usable assemblies that do not have an entry point. I would really like to see other people's answer.

Dependency injection is the responsibility of the entry-point assembly. Yet, if you have a lot of classes and assemblies each needing DI, then it is possible that they are left-off for some classes/assemblies and the task becomes onerous.

Solution One

Using convention over configuration. You stick to a rule of class Foo implementing IFoo, etc. A lot of DI frameworks have the means to set it up using convention.

Solution two

Above solution does not solve all problems since sometimes you need to parameterise the setup of the injection. Here is how I have solved the problem (especially for those assemblies loaded by MEF and this is for AutoFac):

Created an interface IIocInstaller where container (or builder is passed)

public interface IIocInstaller {     void Setup(ContainerBuilder builder); } 

Created an assembly attribute that flags assemblies needing DI:

[AttributeUsage(AttributeTargets.Assembly)] public class ExportAssemblyAttribute : Attribute { } 

In each assembly, I create a class that sets up DI:

[assembly: ExportAssembly] namespace This.That {      [Export(typeof(IIocInstaller))]     public class IocInstaller : IIocInstaller     {         public void Setup(ContainerBuilder builder)         {             ....         }     } } 

Then in the entry point, I have a common code which looks through all loaded assemblies (including MEFed ones) that have the assembly attribute and then look for the type implementing the IIocInstaller and then call Setup on them.

like image 24
Aliostad Avatar answered Sep 28 '22 20:09

Aliostad