我在Global.aspx中有以下代码
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();
}
}
我也有一个基本控制器:
public class BaseController : Controller
{
[Inject]
public IProductService ProductService
{
get;
set;
}
}
此代码有效。我遇到的问题是我想从基本控制器中删除inject属性,并在Ninject ServiceModule中指定它。换句话说,我如何在ServiceModule中编写绑定规则,告诉Ninject将ProductService注入基本控制器的属性?
如果删除该属性,我将收到NullReferenceException。
答案 0 :(得分:3)
基于约定的绑定存在于http://github.com/ninject/ninject.extensions.conventions中 - 一个实现IBindingGenerator
。这主要与发现接口和服务有关。
通常,构造函数注入是一种很好的默认方法。然而,ASP.NET MVC的工作方式使得这更难做(因此FubuMVC等)。因此,物业注入是下一个最佳选择。
您可能会发现在OnActivation
中使用Bind
可能会让您做得足够多 - 如果可以的话,这是迄今为止最简单的。
我会将您尝试做的事情描述为基于约定的激活。问题是:
决定你要自动注入什么。你打算注入一些不具体的公共场合吗?你的内核知道的一切?除非您能够对您想要做的事情做出清晰的定义,否则注射过程可能会变得难以预测且难以理解。你最终会调试并向同事解释很多。
提高效率。 Ninject在幕后动态生成代码,使实例的激活效率很高(即,在课程中寻找[Inject]
标记时,它会生成一次代码,然后像你写的一样进行搜索它很长)。
查看代码,OOTB没有简单的方法。看起来添加自定义IInjectionHeuristic
就可以了。
但是,如果您深入了解容器,则需要
答案 1 :(得分:2)
通过Ruben Bartelink扩展您的想法,您可以创建IInjectionHeuristic的自定义实现。
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;
}
}
ControllerInjectionHeuristic
会在BaseController
上注入内核能够解析服务的任何属性(服务)。
在内核中注册自定义实现。
var kernel = new StandardKernel();
kernel.Components.Add<IInjectionHeuristic, ControllerInjectionHeuristic>();
该问题的另一个解决方案是使用OnActivation
。 (此解决方案未经测试,但它应该让您了解如何继续)。
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>();
}
}