2010-10-06 5 views
5

J'essaie de faire fonctionner l'injection de propriété sur un attribut de filtre d'action personnalisé. Il fonctionne comme il est censé, cependant, je voudrais utiliser DI sur la propriété elle-même. Mon filtre ressemble à ceciInjection de propriété dans un filtre d'action

[AttributeUsage(AttributeTargets.Class)] 
public sealed class HeaderFilterAttribute : ActionFilterAttribute 
{ 
    public IMarketService MarketService 
    { get; set; } 

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     var view = (ViewResultBase)filterContext.Result; 

     if (view != null) 
     { 
      BaseViewModel viewModel = view.ViewData.Model as BaseViewModel; 
      if (viewModel != null) 
       viewModel.Header = GetHeaderScript(); 
     } 
     base.OnActionExecuted(filterContext); 
    } 

    private string GetHeaderScript() 
    { 
    //Use MarketService here and return header script 
    return "script"; 
    } 
} 

Voici comment je configure la propriété en utilisant StructureMap dans ma classe BootStrapper.

  //HeaderFilterAttribute 
     IMarketRepository marketRepository = new SqlMarketRepository(); 
     IMarketService marketService = new MarketService(marketRepository); 
     ObjectFactory.Container.Configure(r => r.ForConcreteType<HeaderFilterAttribute>(). 
              Configure.WithProperty("MarketService"). 
              EqualTo(marketService)); 

Mon problème est que je n'ai pas accès à SqlMarketRepository puisque tous mes types de béton sont injectés via DI et je ne veux vraiment pas utiliser des types concrets dans mon programme d'amorçage. Donc, la question ultime est maintenant, comment puis-je injecter MarketService dans l'attribut Filtre sans recourir à ce qui précède? :)

+0

Le MVC 3 est-il une option? Ceci est intégré. –

+0

Je dois prendre une décision dans un mois Craig et je ne suis pas vraiment sûr que l'équipe approuvera aller avec une édition Preview pour l'utilisation de production :( – Praveen

Répondre

4

Dans votre ObjectFactory.Initialize() appel, ajoutez la ligne suivante:

SetAllProperties(x => x.OfType<IMarketService>()); 

qui injectera l'instance de IMarketService configuré dans une propriété de type IMarketService, sur un objet récupéré à partir du conteneur.

+0

C'est exactement ce dont j'avais besoin.) Merci Josh! – Praveen

1

Je pense que vous avez besoin d'une implémentation d'invocateur d'action personnalisée qui résoudra les filtres. Vous pouvez creuser un échantillon de Windsor sur le implementation de mon entreprise (environ 1/2). Il devrait y en avoir plusieurs autres disponibles en ligne. Je sais que j'en ai vu sur ce site.

PS. J'ai remarqué que vous utilisez un modèle de vue de base pour remplir un en-tête. Je recommande d'utiliser la collection ViewData [] avec une clé statique au lieu de l'héritage dans votre modèle de vue. :)

+0

J'essaie de rester loin de la collection ViewData autant que possible: D. Une raison pour laquelle un type fort serait mauvais dans ce cas? – Praveen

+1

Parce que la composition (via ViewData []) vous permet beaucoup plus de flexibilité que l'héritage des modèles de vue. Imaginez que vous vouliez plus tard ajouter plus de composants (en-tête, menus, barre latérale, widget de profil utilisateur, etc.) à différentes pages. Si vous devez adapter tout cela dans votre modèle de base, il y aura beaucoup de monde et vous n'aurez probablement même pas besoin de tout sur chaque vue. J'utilise le modèle uniquement pour la vue spécifique qui est rendue, puis je place mes autres composants dans ViewData. Exemple de code de vue: 'var headerModel = ViewData [Constants.HeaderData] en tant que HeaderViewModel'. – Ryan

Questions connexes