Asp.net mvc 2 使用Ninject 2在基本控制器中进行属性注入
我的Global.aspx中有以下代码Asp.net mvc 2 使用Ninject 2在基本控制器中进行属性注入,asp.net-mvc-2,ioc-container,ninject,ninject-2,Asp.net Mvc 2,Ioc Container,Ninject,Ninject 2,我的Global.aspx中有以下代码 protected override void OnApplicationStarted() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); RegisterAllControllersIn(Assembly.GetExecutingAssembly()); } protected override IKernel CreateKe
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
RegisterAllControllersIn(Assembly.GetExecutingAssembly());
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new ServiceModule());
}
我还有以下Ninject模块:
internal class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IProductService>().To<ProductService>().InRequestScope();
}
}
这个代码有效。我遇到的问题是,我想从基本控制器中删除inject属性,并在Ninject ServiceModule中指定它。换句话说,我如何在ServiceModule中编写一个绑定规则,告诉Ninject将ProductService注入基本控制器中的属性
如果删除该属性,我将得到一个NullReferenceException。基于约定的绑定存在于--一个实现了
IBindingGenerator
。不过,这主要与发现接口和服务有关
通常,构造函数注入是一种很好的默认方法。然而,ASP.NET MVC的工作方式使得这一点变得更加困难(因此,FubuMVC等)。因此,属性注入是下一个最佳选择
您可能会发现在Bind
中使用OnActivation
可以让您做得足够多-如果可以的话,这是迄今为止最简单的方法
我将描述您试图做的基于约定的激活。问题在于:
- 决定要自动注入的内容。你会把所有不具体的东西都公开吗?内核所知道的一切?除非你能对你想要做的事情给出一个清晰的定义,否则注入过程可能会变得不可预测且难以理解。最后,你会对同事进行大量的调试和解释
- 让它更有效率。Ninject在后台动态生成代码,以使实例的激活更高效(即,在遍历类查找
标记时,它生成一次代码来执行该操作,然后就好像是直接编写的一样进行抖动)[Inject]
iInjection
就可以了
然而,如果你要把这个深的容器,你需要
在Ruben Bartelink的思想基础上进行扩展,您可以创建的自定义实现
ControllerInjectionHeuristic
将在BaseController
上注入内核能够解析服务的任何属性(服务)
向内核注册自定义实现
var kernel = new StandardKernel();
kernel.Components.Add<IInjectionHeuristic, ControllerInjectionHeuristic>();
Ruben,你能提供一个例子,说明我将如何在ServiceModule中编写一个绑定规则,告诉Ninject将ProductService注入到基本控制器的属性中吗?谢谢@托马斯:我从来没有做过这种性质的定制(因为我不相信这是一个好方法,我也不想这样做),不幸的是,我没有时间这么做-对不起。。。(到目前为止,我的答案似乎被认为价值较低,为什么我——我没有任何反馈认为我的答案已被理解或正确?+1很好的工作提供了一个样本,而不是像我一样漫无边际!不确定从MemberInfo转换属性信息的方式是否正确-也许您应该使用
is
/as
?另外,一个TryGet
将生成一个完整的对象,然后将其丢弃。您需要一个CanResolve操作(我想不起它的名称)。在这种情况下,我相信乍一看是可以的,但我个人会花几分钟仔细阅读MSDN文档中的.ReflectedType
,以了解这是否正是我的意思。我认为这将是一个学习的好机会。我执行var propertyInfo=member.ReflectedType.GetProperty(member.Name)的原因
是因为在我的测试项目中,成员
原来是一个RuntimePropertyInfo
,它是一个内部类。所以我就带着a能想到的下一个最好的东西跑了。我选择了kernel.TryService(Type)
而不是kernel.CanResolve(IRequest)
,因为它比构造一个完整的请求简单得多。然而,我相信,ControllerInjectorHeuristic
的性能不会很好。它肯定还没有准备好生产。
public class ControllerInjectionHeuristic : NinjectComponent, IInjectionHeuristic
{
private readonly IKernel kernel;
public BaseControllerInjectionHeuristic(IKernel kernel)
{
this.kernel = kernel;
}
public bool ShouldInject(MemberInfo member)
{
if (member.ReflectedType != typeof(BaseController))
{
return false;
}
var propertyInfo = member.ReflectedType.GetProperty(member.Name);
object service = kernel.TryGet(propertyInfo.PropertyType);
return service != null;
}
}
var kernel = new StandardKernel();
kernel.Components.Add<IInjectionHeuristic, ControllerInjectionHeuristic>();
public class ControllerModule : NinjectModule
{
public override void Load()
{
// Get all controller types. You could use
// Ninject.Extensions.Conventions.
IEnumerable<Type> controllerTypes = null;
foreach (var controllerType in controllerTypes)
{
Bind(controllerType).ToSelf().InRequestScope()
.OnActivation(ControllerActivation);
}
}
private static void ControllerActivation(IContext context, object obj)
{
var controller = obj as BaseController;
if (controller == null)
{
return;
}
controller.ProductService = context.Kernel.Get<IProductService>();
}
}