2009-02-16 3 views
17

Après avoir vu comment NInject can do it et AutoFac can do it J'essaie de comprendre comment injecter des dépendances dans MVC ActionFilters utilisant le château de WindsorComment puis-je utiliser Windsor pour injecter des dépendances dans ActionFilterAttributes

En ce moment je suis en utilisant un statique laid IoC classe d'aide pour résoudre les dépendances du code constructeur comme ceci:

public class MyFilterAttribute : ActionFilterAttribute 
{  
    private readonly IUserRepository _userRepository; 
    public MyFilterAttribute() : this(IoC.Resolve<IUserRepository>()) { } 
    public MyFilterAttribute(IUserRepository userRepository) 
    { 
    _userRepository = userRepository; 
    } 
} 

J'aimerais enlever cette chose statique antimodèle de mes IoC filtres.

Y a-t-il des indices sur comment je ferais ça avec Castle Windsor?

Et non, le changement de cadre DI n'est pas une option.

Répondre

10

Faire un attribut générique: MyFilterAttribute avec cteur prendre un type comme argument - à savoir quelque chose comme ceci:

public class MyFilterAttribute : ActionFilterAttribute { 
    public MyFilterAttribute(Type serviceType) { 
     this.serviceType = serviceType; 
    } 

    public override void OnActionExecuting(FilterExecutingContext c) { 
     Container.Resolve<IFilterService>(serviceType).OnActionExecuting(c); 
     // alternatively swap c with some context defined by you 
    } 

    // (...) action executed implemented analogously 

    public Type ServiceType { get { return serviceType; } } 
    public IWindsorContainer Container { set; get; } 
} 

Ensuite, utilisez la même approche que les deux articles que vous parlez, afin de prendre le contrôle de comment les actions sont appelées, et effectuez une injection manuelle de votre WindsorContainer dans l'attribut.

Utilisation: [MyFilter (typeof (IMyFilterService))]

Votre filtre réel sera alors dans une classe implémentant IMyFilterService qui devrait mettre en œuvre IFilterService qui pourrait ressembler à ceci:

public interface IFilterService { 
    void ActionExecuting(ActionExecutingContext c); 
    void ActionExecuted(ActionExecutedContext c); 
} 

De cette façon, votre filtre ne sera même pas lié à ASP.NET MVC, et votre attribut est simplement un morceau de métadonnées - comme il est supposé être! :-)

+2

Je suis d'accord: les attributs ne doivent pas être "exécutables" mais juste une étiquette. –

+2

merci beaucoup pour votre réponse! Je me suis lancé avec quelques mods: 1) la ligne Container.Resolve nécessite un paramètre générique. Je l'ai changé pour utiliser Container.Resolve (serviceType) et le cast. 2) J'ai hérité de mvccontrib WindsorControllerFactory et ajouté ActionInvoker dans CreateController(). –

18

Lorsque j'en avais besoin, j'ai construit sur le travail que d'autres ont fait avec Ninject et Windsor pour obtenir property injection dependencies on my ActionFilters.

+3

J'ai également préféré la méthode sur ce lien. –

+0

Nice post merci! Je l'ai fait fonctionner très rapidement et l'utilisation est beaucoup plus agréable que l'option générique MyFilterAttribute –

Questions connexes