【问题标题】:Injection of Request Scope objects into MVC ActionFilterAttribute将 Request Scope 对象注入 MVC ActionFilterAttribute
【发布时间】:2015-11-02 23:53:49
【问题描述】:

我有一个购物车服务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)。

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

所以我的问题是 - 这到底是怎么做到的?最近在 Ninject 或 MVC 中做了什么改变,这本来可以让它工作的。

我现在的解决方法是执行以下操作:

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

我真的很困惑这到底是怎么做到的——而且确实做到了。我应该怎么做?

【问题讨论】:

    标签: ninject ninject.web.mvc actionfilterattribute


    【解决方案1】:

    也许虽然过滤器属性只实例化了一次,但每次点击页面时,该属性都是[Injected]-ed。但让我们期待:)

    在 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过滤器的依赖注入章节

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      • 2016-07-17
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      相关资源
      最近更新 更多