我的项目中有几个类库,并且都在使用Ninject
IoC容器。我希望在找到StandardKernel
的任何地方一次性加载INinjectModule
中的所有模块。所以我用过:
var kernel = new StandardKernel();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies())
但由于某些原因,这不起作用。有人可以帮忙吗?
答案 0 :(得分:20)
嗯,这经常发生在声明绑定但是其他模块被加载到该模块试图解析尚未加载的绑定的地方。发生这种情况是因为List<INinjectModule>
的顺序可能不正确。
如果您认为是这种情况。请遵循此决议。
我们的想法是每个程序集都有一个bootstapper
,其中引导程序将负责按逻辑顺序加载模块。
让我们考虑一个bootstrapper的接口(我们将用它来查找程序集中的bootstrapper)
public interface INinjectModuleBootstrapper
{
IList<INinjectModule> GetModules();
}
现在考虑使用DataAccess程序集,实现INinjectModuleBootstrapper
:
public class DataAccessBootstrapper : INinjectModuleBootstrapper
{
public IList<INinjectModule> GetModules()
{
//this is where you will be considering priority of your modules.
return new List<INinjectModule>()
{
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
}
}
这就是你为所有装配定义Bootstrapper
的方法。现在,从程序启动开始,我们需要加载所有模块的StandardKernel
。我们会写这样的东西:
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
return BootstrapHelper.LoadNinjectKernel(assemblies);
我们的BootstrapperHelper
课程是:
public static class BootstrapHelper
{
public static StandardKernel LoadNinjectKernel(IEnumerable<Assembly> 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;
}
}
答案 1 :(得分:3)
您应该检查的另一件事是扩展NinjectModule的类是否为public,否则它在Assembly中不可见。
答案 2 :(得分:0)
我认为使用CurrentDomain.GetAllAssemblies()不是一个好主意,因为并非所有项目程序集都可以在程序启动时加载(某些程序集可以加载到用户操作上,例如或其他事件)。在这种情况下,您将拥有依赖项的空引用异常。
答案 3 :(得分:0)
您可以使用反射来查找和实例化Ninject模块:
BuildManager.GetReferencedAssemblies()
.Cast<Assembly>()
.SelectMany(a => a.DefinedTypes)
.Where(t => typeof(INinjectModule).IsAssignableFrom(t))
.Select(t => (INinjectModule)Activator.CreateInstance(t))