問題是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