I am developing a class library that uses dependency injection and inversion of control.
As I understand it, the ideal IoC setup has only a single composition root in the main application. The library should register its dependencies with the root, so I'd like to expose a call that allows the main program to do this. The call might look like this:
void RegisterDependencies(Container container)
{
...
and be called like this:
//In the main program (which we are not writing)
static Container CompositionRoot()
{
var builder = new ContainerBuilder();
//Main program registers its own dependencies
builder.RegisterType<IMainProgramType, MainProgramClass>();
//Main program calls library to register the library's dependencies
MyLibrary.Root.RegisterDependencies(builder); //<<<<< the call I want to enable
return builder.Builder();
}
The problem with the above is that the RegisterDependencies call must accept a parameter that contains the IoC container or some object that is used to build it. But the team writing the library doesn't know what container the main program is going to use, and we don't want to impose a limitation on it.
How to solve this problem? Is there a common interface we could expose, e.g.
//In my library
void RegisterDepencendies(IStandardContainer container)
Or perhaps expose it as a delegate?
//In my library
void RegisterDependencies(Action<object,object> registerAction)
{
registerAction(typeof(IMyLibraryInterface), typeof(MyLibraryClass));
}
//In main program
MyLibrary.Root.RegisterDependencies( i,c => builder.RegisterType(i,c) );
Or should we abandon this approach and allow the library to have its own composition root and its own container?