Внедрение зависимостей в фильтры действий ASP.NET MVC 3. Что плохого в таком подходе?

Вот установка. Скажем, у меня есть какой-то фильтр действий, которому нужен экземпляр службы:

public interface IMyService
{
   void DoSomething();
}

public class MyService : IMyService
{
   public void DoSomething(){}
}

Затем у меня есть ActionFilter, которому нужен экземпляр этой службы:

public class MyActionFilter : ActionFilterAttribute
{
   private IMyService _myService; // <--- How do we get this injected

   public override void OnActionExecuting(ActionExecutingContext filterContext)
   {
       _myService.DoSomething();
       base.OnActionExecuting(filterContext);
   }
}

В MVC 1/2 внедрение зависимостей в фильтры действий было немного затруднительным. жопа. Наиболее распространенным подходом было использование средства вызова настраиваемого действия, как показано здесь: http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action- filter / Основная мотивация этого обходного пути заключалась в том, что следующий подход считался небрежным и жестким соединением с контейнером:

public class MyActionFilter : ActionFilterAttribute
{
   private IMyService _myService;

   public MyActionFilter()
      :this(MyStaticKernel.Get()) //using Ninject, but would apply to any container
   {

   }

   public MyActionFilter(IMyService myService)
   {
      _myService = myService;
   }

   public override void OnActionExecuting(ActionExecutingContext filterContext)
   {
       _myService.DoSomething();
       base.OnActionExecuting(filterContext);
   }
}

Здесь мы используем внедрение конструктора и перегружаем конструктор, чтобы использовать контейнер и внедрить службу. Я согласен с тем, что контейнер тесно связан с ActionFilter.

Мой вопрос вот в чем: теперь в ASP.NET MVC 3, где у нас есть абстракция используемого контейнера (через DependencyResolver), все эти обручи все еще необходимо? Позвольте мне продемонстрировать:

public class MyActionFilter : ActionFilterAttribute
{
   private IMyService _myService;

   public MyActionFilter()
      :this(DependencyResolver.Current.GetService(typeof(IMyService)) as IMyService)
   {

   }

   public MyActionFilter(IMyService myService)
   {
      _myService = myService;
   }

   public override void OnActionExecuting(ActionExecutingContext filterContext)
   {
       _myService.DoSomething();
       base.OnActionExecuting(filterContext);
   }
}

Теперь я знаю, что некоторые пуристы могут посмеяться над этим, но если серьезно, что будет обратной стороной? Он по-прежнему поддается тестированию, поскольку вы можете использовать конструктор, который принимает IMyService во время тестирования, и таким образом внедрять фиктивный сервис. Вы не привязаны к какой-либо реализации контейнера DI, поскольку используете DependencyResolver, поэтому есть ли у этого подхода какие-либо недостатки?

Кстати, вот еще один хороший подход для выполнения этого в MVC3 с использованием нового интерфейса IFilterProvider: http://www.thecodinghumanist.com/blog/archives/2011/1/27/structuremap-action-filters-and-dependency-injection-in-asp-net-mvc-3

77
задан TrueWill 25 August 2011 в 22:38
поделиться