我有一个购物车服务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;
}
}
我真的很困惑,虽然这怎么可能有效 - 而且它确实做到了。我该怎么做呢?
答案 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(章节过滤器的依赖注入)