在Ninject的所有程序集中加载模块
本文关键字:程序集 集中 加载 模块 程序 Ninject | 更新日期: 2023-09-27 18:12:22
我在我的项目中有几个类库,所有都使用Ninject
IoC容器。我想一次加载StandardKernel
中的所有模块,只要找到INinjectModule
。所以我使用:
var kernel = new StandardKernel();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies())
但由于某些原因,这不起作用。有人能帮忙吗?
嗯,这种情况经常发生在声明了绑定,但加载了其他模块,而该模块试图解析尚未加载的绑定时。这是因为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;
}
}
你应该检查的另一件事是,如果扩展了NinjectModule的类是公共的,否则它将不会在程序集中可见。
我认为使用CurrentDomain.GetAllAssemblies()不是一个好主意,因为不是所有的项目程序集都可以在程序启动时加载(有些程序集可以在用户操作中加载,例如或其他事件)。在这种情况下,您将对依赖项有空引用异常。
您可以使用反射来查找和实例化Ninject模块:
BuildManager.GetReferencedAssemblies()
.Cast<Assembly>()
.SelectMany(a => a.DefinedTypes)
.Where(t => typeof(INinjectModule).IsAssignableFrom(t))
.Select(t => (INinjectModule)Activator.CreateInstance(t))