我有一个MVC4应用程序,它使用反射在运行时加载控制器。这些控制器以及主应用程序使用Ninject将内容注入构造函数。
每个动态控制器都维护一个所需的所有绑定列表,并将它们存储为主应用程序在运行时加载的Ninject模块。
我目前在多个动态控制器包含相同绑定时遇到问题。我希望动态控制器是自包含的,所以我不想从控制器项目中删除绑定,我真的不想解析txt或xml文档来读取所有绑定。
有没有办法删除重复绑定或告诉Ninject使用它遇到的第一个绑定(如果有多个绑定)。
加载所有引用的程序集绑定
public static StandardKernel LoadNinjectKernel(IEnumerable<Assembly> assemblies)
{
var kernel = new StandardKernel();
foreach (var asm in assemblies)
{
asm
.GetTypes()
.Where(t =>
t.GetInterfaces()
.Any(i =>
i.Name == typeof(INinjectBootstrapper).Name))
.ToList()
.ForEach(t =>
{
var ninjectModuleBootstrapper =
(INinjectBootstrapper)Activator.CreateInstance(t);
kernel.Load(ninjectModuleBootstrapper.GetModules());
});
}
return kernel;
}
绑定类
public class NinjectBindings : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<IDMSService>().To<DMSService>();
Bind<ICaseManagerRepo>().To<CaseManagerRepo>();
}
}
控制器工厂
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
if (controllerType != null)
{
return (IController)kernel.Get(controllerType);
}
else
{
return base.GetControllerInstance(requestContext, controllerType);
}
}
答案 0 :(得分:2)
不,没有。
您可以尝试查看使用IBindingRoot.Rebind
代替Bind
是否符合您的需要。
但是我会强烈建议反对它,因为它不适用于:
即使你让它工作,当你有任何条件,参数,OnActivation / OnDeactivation时,你最终会遇到很多代码重复和难以查明的问题(这些问题是否有效取决于模块加载序列)。这真的不是一条路。
相反,你可以做一直做的事情:消除重复。
将多个位置需要的绑定移动到自己的模块。
创建一些类型(让我们称之为ControllerModules
),指定一个控制器需要哪些模块。
找到所有ControllerModules
,从中读取模块,然后加载所有这些模块,而不是加载所有模块。
在伪代码中,这可能看起来像:
IEnumerable<Type> modulesToLoad = Assemblies.InPath(...)
.SelectAllClasses()
.InheritingFrom<ControllerModules>
.SelectMany(x => x.RequiredModules)
.Distinct();
IKernel.Load(modulesToLoad);