L'injection de dépendances dans ASP.NET MVC 3 filtres d'actions. Quel est le problème avec cette approche?

Voici la configuration. Dire que j'ai un peu d'action, filtre a besoin d'une instance d'un service:

public interface IMyService
{
   void DoSomething();
}

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

J'ai ensuite une ActionFilter qui a besoin d'une instance de ce service:

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 l'injection de dépendances dans l'action des filtres était un peu d'une douleur dans le cul. L'approche la plus commune est d'utiliser un appelant d'action comme on peut le voir ici: http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/ La motivation principale derrière cette solution de contournement a été parce que cette approche suivante a été considéré comme bâclée et le couplage avec le conteneur:

public class MyActionFilter : ActionFilterAttribute
{
   private IMyService _myService;

   public MyActionFilter()
      :this(MyStaticKernel.Get<IMyService>()) //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);
   }
}

Ici nous sommes à l'aide du constructeur d'injection et de surcharger le constructeur à utiliser le conteneur et injecter le service. Je suis d'accord que ne couplent le récipient avec le ActionFilter.

Ma question est: est-ce Maintenant dans ASP.NET MVC 3, où nous avons une abstraction du récipient utilisé (par le biais de la DependencyResolver) sont tous ces cerceaux-elle encore nécessaire? Permettez-moi de démontrer:

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);
   }
}

Maintenant, je sais que certains puristes pourraient se moquer de cela, mais sérieusement, quel serait l'inconvénient? C'est toujours vérifiable que vous pouvez utiliser le constructeur qui prend un IMyService au temps de test et d'injecter une maquette au service de cette façon. Vous n'êtes pas lié à la mise en œuvre des DI conteneur puisque vous êtes à l'aide de la DependencyResolver, alors y at-il des inconvénients à cette approche?

D'ailleurs, voici une autre bonne approche pour ce faire dans MVC3 à l'aide de la nouvelle IFilterProvider interface: http://www.thecodinghumanist.com/blog/archives/2011/1/27/structuremap-action-filters-and-dependency-injection-in-asp-net-mvc-3

  • Merci pour les liens vers mon post :). Je pense que ce serait bien. Malgré les articles de mon blog plus tôt cette année, je ne suis pas un grand fan de la DI-elles incluses dans MVC 3 et les ont pas été à l'aide de ces derniers temps. Il semble que le travail, mais se sent un peu maladroit parfois.
  • Si vous utilisez Ninject, cela pourrait être une approche possible: stackoverflow.com/questions/6193414/...
  • +1, bien que le service locator est considéré comme un anti-modèle par beaucoup de gens, je pense que je préfère votre approche sur les Marques pour sa simplicité et le fait que la dépendance est résolu en un seul endroit, le conteneur IOC, tandis que dans la Marque de l'exemple que vous auriez à résoudre en deux endroits, dans le programme d'amorçage et lors de l'enregistrement de l'filtres globaux, qui se sent mal.
  • vous pouvez toujours utiliser le "DependencyResolver.Actuel.La méthode GetService(Type) n'importe quand vous voulez.
InformationsquelleAutor BFree | 2011-08-25