我在项目中有几个类库,所有的类库都使用Ninject
IoC容器。我想要在一个StandardKernel
中一次性加载所有的模块,无论何时发现一个INinjectModule
。因此,我使用了以下代码:
var kernel = new StandardKernel();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies())
但是出于某种原因,这并不起作用。有人可以帮忙吗?
我在项目中有几个类库,所有的类库都使用Ninject
IoC容器。我想要在一个StandardKernel
中一次性加载所有的模块,无论何时发现一个INinjectModule
。因此,我使用了以下代码:
var kernel = new StandardKernel();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies())
但是出于某种原因,这并不起作用。有人可以帮忙吗?
当声明绑定但加载其他模块时,经常会出现这种情况,其中该模块尝试解析尚未加载的绑定。这是因为List<INinjectModule>
可能不在正确的顺序中。
如果您认为这是原因,请按照以下解决方案进行操作。
我们的想法是为每个程序集提供一个bootstrapper
,其中bootstrapper将负责按其逻辑顺序加载模块。
让我们考虑一个用于引导启动器的接口(我们将使用此接口在程序集中查找引导启动器)
public interface INinjectModuleBootstrapper
{
IList<INinjectModule> GetModules();
}
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;
}
}
另外一个需要检查的是继承 NinjectModule 的类是否为 public,否则它将无法在程序集中被找到。
BuildManager.GetReferencedAssemblies()
.Cast<Assembly>()
.SelectMany(a => a.DefinedTypes)
.Where(t => typeof(INinjectModule).IsAssignableFrom(t))
.Select(t => (INinjectModule)Activator.CreateInstance(t))
我认为使用CurrentDomain.GetAllAssemblies() 不是一个好主意,因为并非所有项目程序集都可以在程序启动时加载(例如,某些程序集可能会在用户操作或其他事件上加载)。在这种情况下,您将遇到依赖项的空引用异常。