在Ninject中的所有程序集中加载模块

我的项目中有几个类库,并且都使用Ninject IoC容器。 我希望在找到INinjectModule任何地方INinjectModule加载StandardKernel中的所有模块。 所以我用过:

 var kernel = new StandardKernel(); kernel.Load(AppDomain.CurrentDomain.GetAssemblies()) 

但由于某种原因,这不起作用。 有人可以帮忙吗?

嗯,这经常发生在声明绑定但是其他模块被加载到该模块试图解析尚未加载的绑定时。 发生这种情况是因为List的顺序可能不正确。

如果您认为是这种情况。 遵循此决议。

我们的想法是每个程序集都有一个bootstapper ,其中bootstrapper将负责按逻辑顺序加载模块。

让我们考虑一下bootstrapper的接口(我们将用它来查找程序集中的bootstrapper)

 public interface INinjectModuleBootstrapper { IList GetModules(); } 

现在考虑为您的DataAccess程序集,实现INinjectModuleBootstrapper

 public class DataAccessBootstrapper : INinjectModuleBootstrapper { public IList GetModules() { //this is where you will be considering priority of your modules. return new List() { new DataObjectModule(), new RepositoryModule(), new DbConnectionModule() }; //RepositoryModule cannot be loaded until DataObjectModule is loaded //as it is depended on DataObjectModule and DbConnectionModule has //dependency on RepositoryModule } } 

这就是你为所有assembly定义Bootstrapper的方法。 现在,从程序启动开始,我们需要加载所有模块的StandardKernel 。 我们会写这样的东西:

 var assemblies = AppDomain.CurrentDomain.GetAssemblies(); return BootstrapHelper.LoadNinjectKernel(assemblies); 

我们的BootstrapperHelper类是:

 public static class BootstrapHelper { public static StandardKernel LoadNinjectKernel(IEnumerable assemblies) { var standardKernel = new StandardKernel(); foreach (var assembly in assemblies) { assembly .GetTypes() .Where(t => t.GetInterfaces() .Any(i => i.Name == typeof(INinjectModuleBootstrapper).Name)) .ToList() .ForEach(t => { var ninjectModuleBootstrapper = (INinjectModuleBootstrapper)Activator.CreateInstance(t); standardKernel.Load(ninjectModuleBootstrapper.GetModules()); }); } return standardKernel; } } 

您应该检查的另一件事是扩展NinjectModule的类是否为public,否则它在Assembly中不可见。

我认为使用CurrentDomain.GetAllAssemblies()并不是一个好主意,因为并非所有项目程序集都可以在程序启动时加载(某些程序集可以加载到用户操作上,例如或其他事件)。 在这种情况下,您将具有依赖项的空引用exception。

您可以使用reflection来查找和实例化Ninject模块:

 BuildManager.GetReferencedAssemblies() .Cast() .SelectMany(a => a.DefinedTypes) .Where(t => typeof(INinjectModule).IsAssignableFrom(t)) .Select(t => (INinjectModule)Activator.CreateInstance(t))