2015-11-02 1 views
0

У меня есть корзина службы IShoppingCartService, который определен с Ninject как InRequestScopeИнъекция Request Scope объектов в MVC ActionFilterAttribute

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

Возможно,, в то время как атрибут фильтра был создан только один раз, свойство было [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 (глава Dependency Injection для фильтров)

Смежные вопросы