2012-08-02 95 views
1

我正在尝试将一个属性注入到我的一个名为UnitOfWorkAttribute的ActionFilter中。我有这样的代码:用Ninject注入MVC​​ 3中的属性

[Inject] 
public IUnitOfWork UnitOfWork { get; set; } 

在此之前得到执行,我告诉Ninject一起解决此问题:

Bind<IUnitOfWork>().To<NHibernateUnitOfWork>().InThreadScope(); 

我的问题是,在我的UnitOfWorkAttribute类,每当我试图用我的UnitOfWork属性,它通过为空。这是我的接口:

public interface IUnitOfWork : IDisposable 
{ 
    void Begin(); 
    void Commit(); 
    void Rollback(); 
} 

,这是我具体:

public interface INHibernateUnitOfWork : IUnitOfWork 
{ 
    ISession Session { get; } 
} 

public class NHibernateUnitOfWork : INHibernateUnitOfWork 
{ 
    private readonly ISessionSource sessionSource; 
    private ITransaction transaction; 
    private ISession session; 

    private bool disposed; 
    private bool begun; 

    public NHibernateUnitOfWork(ISessionSource sessionSource) 
    { 
     this.sessionSource = sessionSource; 
     Begin(); 
    } 

    //....... 
} 

我履行//下的接口......

什么我错在这里做?

回答

6

问题是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,因此我们的富实例将在自定义动作过滤器中填充。

+2

这很好,但很大程度上不需要。 Ninject.MVC提供了一个很好的叫做BindFilter的小功能,你可以在这里阅读它https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations – 2012-08-02 16:55:22

+0

@MystereMan只有一种方法可以做事吗? – BFree 2012-08-02 16:59:33

+0

不,但有点像给他人配方时,他们想知道的是他们可以得到一些饼干。 – 2012-08-02 17:01:46