We have created a WebApi solution using Autofac for DI. We broke out the bootstrapping of our autofac into a separate project. This way, our WebApi project only references our Bootstrap and Contracts projects. Our bootstrap project then references all other assemblies and wires everything together. I like this design for separation of concerns.
We can manually load our assemblies as follows - where our "AutofacModule" classes contain the necessary info to register each module (assembly).
ContainerBuilder builder = new Autofac.ContainerBuilder();
builder.RegisterModule(new Business.AutofacModule());
builder.RegisterModule(new Data.AutofacModule());
builder.RegisterModule(new Services.AutofacModule());
etc...
This works, but requires hardcoding each assembly. We are trying to make this dynamic so that we can just loop over all referenced assemblies as follows.
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
foreach (var assembly in assemblies)
{
builder.RegisterAssemblyModules(assembly);
}
This should work but doesn't. The problem is that .Net determines various assemblies aren't actually used from within the bootstrap project and doesn't load them (in an attempt to optimize?). So some of our assemblies are never loaded.
I have also tried the following to loop through the bin directory to find all assemblies. However, during compilation, .Net doesn't move the non-referenced assemblies into the bin directory, so they aren't there either.
string assemblyPath = System.IO.Path.Combine(
System.AppDomain.CurrentDomain.BaseDirectory, "bin");
var allAssemblies = new List<Assembly>();
foreach (string dll in Directory.GetFiles(assemblyPath, "*.dll"))
{
allAssemblies.Add(Assembly.LoadFile(dll));
}
I have set the assemblies to Copy Local which didn't work. I read about a Copy Local bug and tried workarounds for that which didn't work either.
Has anyone been able to solve this issue? It seems like Autofac would provide a solution, but all I found was a To Do page on their documents: http://autofac.readthedocs.org/en/latest/faq/isolate-autofac.html
The following two questions are similar, but none of the proposed solutions overcome the fact that the needed assemblies are not in the bin directory.
Not all assemblies are being loaded into AppDomain from the bin folder
Loading all referenced assemblies .NET even if not used explicitly in code
Finally, I'm curious, is this an Autofac specific problem? How do other DI containers solve this problem? I found a similar problem for NInject. Loading unreferenced dll MVC Ninject
//Short answer
Have you seen this: http://docs.autofac.org/en/latest/faq/iis-restart.html It looks like you can scan the referenced assemblies and force them to load.
//Suggestion (or opinion if you like)
Personally I wouldn't have assemblies loaded that weren't going to be used just to be able to have a separate project for the bootstrapping. I don't see the benefit of having it in it's own project. Keep in mind that DI is just that, you are injecting your dependencies of "that" project. Each project can have it's own dependencies and the separation of concern comes from the bootstrapping class, not that it's in it's own project. If you needed to break out just your business logic project into a nuget package that other projects in your company would use you would not want them to also have to download the DI project package that in turn now needs other packages that it may never use. If your dependencies are contained in the project that needed them it becomes modular and extensible. This part of the answer is debatable of course but should be considered at the least.
In case you have multiple projects in your solution, each with their own IoC container class, use the following to load all assemblies, and then register each module in that Assembly.
This is an extension method of the ContainerBuilder.
The above can be called on an instance of your ContainerBuilder as follow:
This should help you. It takes all the assemblies in the bin folder, starting with name MyModule.
This will load those assemblies also which are not even referenced.