将Request Scope对象注入MVC​​ ActionFilterAttribute

时间:2015-11-02 23:53:49

标签: ninject ninject.web.mvc actionfilterattribute

我有一个购物车服务IShoppingCartService,其定义为Ninject为InRequestScope

  this.Bind<IShoppingCartService>().To<ShoppingCartService>().InRequestScope();

它加载用户的购物车并在内部缓存它。请求结束后,服务对象就会消失。

我需要在ActionFilter内访问购物车,因此我使用了[Inject]属性。

public class MyActionFilterAttribute : ActionFilterAttribute
{
    [Inject]
    public IShoppingCartService ShoppingCartService
    {
       get; set;
    }
}

然后我可以在动作过滤器中使用它,就像这样

 public override void OnActionExecuted(ActionExecutedContext filterContext)
 {
       var cart = ShoppingCartService.ShoppingCart;
       ...
 }

现在是奇怪的部分。这已经好了一年或更长时间 - 然后突然(最近升级Ninject和MVC之后)我注意到购物车正在被缓存(即不是InRequestScope)。

在进一步研究中,我看到ActionFilters是单例(我验证了这一点,因为构造函数只被调用过一次)。因此,一旦加载购物车的实例,它就会被永久锁定。

所以我的问题是 - 这究竟是如何运作的? Ninject或MVC最近发生了一些改变,可以让它在以前工作。

我现在的修复方法是执行以下操作:

 public IShoppingCartService ShoppingCartService
 {
     get
     {
         var scs = (IShoppingCartService) DependencyResolver.Current.GetService(typeof(IShoppingCartService));
         return scs;
     }
 }

我真的很困惑,虽然这怎么可能有效 - 而且它确实做到了。我该怎么做呢?

1 个答案:

答案 0 :(得分:1)

可能虽然filter属性仅实例化一次,但每次页面被点击时,属性都为[Injected]。但是让我们期待:)

2010年,Ninject.MVCx(x = 3,5,..)实施了一种“新”方式,介绍如何将内容注入动作过滤器。它不需要依赖属性,它支持构造函数注入。这是它的样子:

公平警告:我通常不会进行asp.net开发,如果以下内容确实改变了IActionFilter的生命周期,我就不会尝试所以你必须自己尝试一下。如果你这样做,请提供反馈)

public class MyActionFilter : IActionFilter
{
    private readonly IShoppingCartService shoppingCartService;

    public MyActionFilter(IShoppingCartService shoppingCartService)
    {
        this.shoppingCartService = shoppingCartService;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var cart = ShoppingCartService.ShoppingCart;
        ...
    }
}

然后需要使用特殊方法BindFilter绑定过滤器:

this.BindFilter<MyActionFilter>(FilterScope.Action, 0)
    .WhenControllerTypeIs<YourController>();

将其应用于YourController的所有操作。

您还可以使用以下目标来应用过滤器:

// Is applied to all actions of controllers which have the FooAttribute
this.BindFilter<MyActionFilter>(FilterScope.Action, 0)
    .WhenControllerHas<FooAttribute>();

// Is applied to all actions which have the FooAttribute
this.BindFilter<MyActionFilter>(FilterScope.Action, 0)
    .WhenActionHas<FooAttribute>();

// Is applied to all actions named Index
this.BindFilter<MyActionFilter>(FilterScope.Action, 0)
    .When((controllerContext,  actionDescriptor) =>
        actionDescriptor.ActionName == "Index");

有一些更多信息可以在Remo Gloor的精彩文章中找到:Official Ninject MVC extension gets support for MVC3(章节过滤器的依赖注入