问题是Ninject从来没有机会在ActionFilter上“做这件事”,这是在MVC内部由FilterAttributeFilterProvider
处理的。你需要做的是告诉MVC使用自定义FilterAttributeFilterProvider
,你可以在它们被执行之前拦截过滤器。请允许我以证明:
说我有这个接口和实现:
public interface IFoo
{
}
public class Foo : IFoo
{
}
然后,我有一个ActionFilter:
public class MyActionFilterAttribute : ActionFilterAttribute
{
public MyActionFilterAttribute()
{
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//do something with Foo
base.OnActionExecuting(filterContext);
}
[Inject]
public IFoo Foo { get; set; }
}
然后我们有一个控制器:
public class HomeController : Controller
{
[MyActionFilter]
public ActionResult Index()
{
return View();
}
}
如果你现在按原样运行,显然Foo在MyActionFilter中仍然是null,所以让我们k EEP去....
让我们建立了Ninject DependencyResolver:
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IKernel _kernel;
public NinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _kernel.GetAll(serviceType);
}
}
现在让我们使用的是在Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
DependencyResolver.SetResolver(new NinjectDependencyResolver(GetKernel()));
}
private IKernel GetKernel()
{
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<Foo>();
return kernel;
}
越来越近了,但仍然MVC不有创建动作过滤器时使用Ninject内核的方法。这是我们将要实现的目标。
第一:
public class NinjectFilterProvider : FilterAttributeFilterProvider
{
private readonly IKernel _kernel;
public NinjectFilterProvider(IKernel kernel)
{
_kernel = kernel;
}
public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var filters = base.GetFilters(controllerContext, actionDescriptor);
foreach (var filter in filters)
{
_kernel.Inject(filter.Instance);
}
return filters;
}
}
这里发生的事情是,我们正在创建一个自定义FilterAttributeFilterProvider类。在OnActionExecuting方法中,在我们通过基础实现获取所有过滤器之后,我们可以调用Ninjects Inject方法,该方法将检查实例并查看它是否可以向其中注入任何内容(使用Inject属性)。
的最后一块拼图是建立我们的定制FilterAttributeFilterProvider绑定:
全球。ASAX:
private IKernel GetKernel()
{
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<Foo>();
//use our custom NinjectFilterProvider
kernel.Bind<IFilterProvider>().To<NinjectFilterProvider>();
return kernel;
}
现在,当MVC去得到一个IFilterProvider
(它通过DependencyResolver会自动完成),它不会得到默认FilterAttributeFilterProvider
而是会得到我们的定制NinjectFilterProvider
,因此我们的富实例将在自定义动作过滤器中填充。
这很好,但很大程度上不需要。 Ninject.MVC提供了一个很好的叫做BindFilter的小功能,你可以在这里阅读它https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations – 2012-08-02 16:55:22
@MystereMan只有一种方法可以做事吗? – BFree 2012-08-02 16:59:33
不,但有点像给他人配方时,他们想知道的是他们可以得到一些饼干。 – 2012-08-02 17:01:46