@fquednau: I like this idea! I have modified it a little, here's how:
Working on the premise that I may not want to load all modules in a
dll (I'd rather be explicit), I created a new interface:
using Ninject.Core;
namespace MyProject.Common.NinjectIoc
{
public interface INinjectModulesToLoad
{
IModule[] RequiredModules { get; }
}
}
Then I created a 'ninject module autoloader' interface and class:
namespace MyProject.Common.NinjectIoc
{
public interface INinjectModuleAutoLoader
{
void InitAndLoadModulesForLoadedAssemblies();
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using Ninject.Core;
namespace MyProject.Common.NinjectIoc
{
public class NinjectModuleAutoLoader : INinjectModuleAutoLoader
{
private readonly IKernel kernel;
public NinjectModuleAutoLoader(IKernel kernel)
{
this.kernel = kernel;
}
public void InitAndLoadModulesForLoadedAssemblies()
{
foreach (Assembly a in
AppDomain.CurrentDomain.GetAssemblies())
{
LoadModulesFromAssembly(a);
}
AppDomain.CurrentDomain.AssemblyLoad +=
new
AssemblyLoadEventHandler(CurrentDomain_AssemblyLoad);
}
private void LoadModulesFromAssembly(Assembly assembly)
{
foreach (IModule[] modules in
FindAllModulesToLoad(assembly))
{
kernel.Load(modules);
}
}
private IEnumerable<IModule[]> FindAllModulesToLoad(Assembly
assembly)
{
foreach (Type t in assembly.GetTypes())
{
if (!t.IsAbstract && t.IsPublic &&
t.GetInterface(typeof(INinjectModulesToLoad).FullName) != null)
{
INinjectModulesToLoad modulesToLoad =
(INinjectModulesToLoad)Activator.CreateInstance(t);
yield return modulesToLoad.RequiredModules;
}
}
}
private void CurrentDomain_AssemblyLoad(object sender,
AssemblyLoadEventArgs args)
{
LoadModulesFromAssembly(args.LoadedAssembly);
}
}
}
The AssemblyLoad event is now monitored and any assemblies that load
in the future should also be caught.
Each assembly now has at least one class which implements
INinjectModulesToLoad.
And to kick-start the process:
IKernel kernel = new StandardKernel();
INinjectModuleAutoLoader moduleAutoLoader = new
NinjectModuleAutoLoader(kernel);
moduleAutoLoader.InitAndLoadModulesForLoadedAssemblies();
Now I don't need to reference my data access layer from my service
layer!
ONce again, thanks fquednau for planting the seed :-)