2009-06-23 10 views

Répondre

1

Vous avez deux options

La première option consiste à écrire un ActionInvoker sur mesure, ce qui est presque aussi dur que cela puisse paraître. Découvrez ce blog post. Il traite spécifiquement de NInject, mais Unity prend en charge l'injection de propriété afin que vous puissiez modifier l'exemple pour utiliser Unity.

Cette option permet de coupler votre conteneur IoC et n'est pas recommandée.

public class MyFilter 
{ 
    IMyService MyService {get; set;} 

    MyFilter() : MyFilter(MyUnityContainer.Resolve<IMyService>()) 
    { } 

    MyFilter(IMyService service) 
    { 
    MyService = service; 
    } 
} 
+0

j'ai essayé la solution trouvée dans le billet de blog, mais il semble y avoir quelques différences entre l'unité et Ninject, ou bien quelque part, le code de quelqu'un est mal :). Les filtres sont en lecture seule au moment où ils sont remplacés par les "InvokeExceptionFilters" remplacés. Je peux donc déclarer un nouveau filtre et injecter des dépendances, mais si j'essaie d'injecter des dépendances sur la liste fournie d'ExceptionFilters, rien ne se passe. Je pourrais créer un nouveau filtre et le passer à la classe de base, mais alors je perdrais toutes les informations déclaratives fournies sur l'attribut lui-même. –

2

Ok, compris.

La plupart du temps, j'ai utilisé la solution de Ben ci-dessus à partir du blog qu'il a pointé.

Le problème est que Unity se comporte un peu différemment.

Vous ne pouvez pas injecter des dépendances directement sur les filtres, car ils sont respectivement de type IActionFilter et IExceptionFilter. Cela m'a amené à croire qu'ils étaient en lecture seule, ce qui n'est pas le cas. C'est juste que Unity doit connaître le type explicite pour injecter. Par conséquent, dans la méthode substituée fournie par l'article, les utilisateurs Unity doivent interroger les filtres pour les types en question, puis les créer.

public UnityActionInvoker(IUnityContainer container, IList<Type> typesToInject) 
     { 
      _container = container; 
      _typesToInject = typesToInject; 
     } 

Et puis dans la méthode surchargée, faire quelque chose comme ceci:

var needsInjection = filters.Where(filter => typesToInject.Contains(filter.GetType())); 

Un peu en désordre, mais il ne doit être fait une fois, et conserve tout ce découplé Ben suggère.

L'autre Gotcha est que vous ne pouvez pas appeler _container.BuildUp (filtre) dans une boucle foreach, car le filtre est en lecture seule dans ce contexte.

1

Moi aussi, je suis tombé sur ce problème et ont maintenant une solution de travail. Il est similaire à la solution décrite ci-dessus mais avec de légères différences et également avec le code Unity complet ajouté.

Tout d'abord je vais utiliser l'injection de propriété pour la raison décrite ci-dessus et, comme ci-dessus, je vais utiliser la méthode de colmatages sur l'unité pour injecter les propriétés dans les filtres déjà créés. Pour ce faire, tous mes contrôleurs héritent d'une nouvelle classe de base personnalisée. Sur cette classe de base, je substitue la méthode CreateActionInvoker afin de définir mon propre ActionInvoker personnalisé.

Protected Overrides Function CreateActionInvoker() As System.Web.Mvc.IActionInvoker 
    Return CustomActionInvoker 
End Function 

Ensuite, dans mon CustomActionInvoker, je remplace la méthode GetFilters.

Protected Overrides Function GetFilters(ByVal controllerContext As ControllerContext, ByVal actionDescriptor As ActionDescriptor) As FilterInfo 
    Dim info = MyBase.GetFilters(controllerContext, actionDescriptor) 

    For Each MyAuthorizationFilter In info.AuthorizationFilters 
     MvcApplication.Container.BuildUp(MyAuthorizationFilter.GetType, MyAuthorizationFilter) 
    Next 

    For Each MyActionFilter In info.ActionFilters 
     MvcApplication.Container.BuildUp(MyActionFilter.GetType, MyActionFilter) 
    Next 

    For Each MyResultFilter In info.ResultFilters 
     MvcApplication.Container.BuildUp(MyResultFilter.GetType, MyResultFilter) 
    Next 

    For Each MyExceptionFilter In info.ExceptionFilters 
     MvcApplication.Container.BuildUp(MyExceptionFilter.GetType, MyExceptionFilter) 
    Next 

    Return info 
End Function 

Contrairement à ce qui est dit plus haut, je n'ai pas trouvé que faire l'accumulation dans une boucle For Each a causé aucun problème.J'ai également surmonté le problème original de n'avoir que l'objet référencé via une interface en utilisant l'une des autres surcharges de la méthode BuildUp qui prend un System.Type ainsi que l'objet existant.

Avec tout ce qui précède fait, je peux maintenant injecter des dépendances directement dans mes filtres.

Tous les commentaires et pensées très apprécié.

Vive Mike