2013-09-25 3 views
10

Sto cercando di trovare un modo per utilizzare Ninject per iniettare le dipendenze del costruttore nei filtri. Sto trovando molti articoli che descrivono l'iniezione di proprietà che è ora sconsigliato, ma il resto degli articoli coinvolge configurazioni complesse con fabbriche, locatori, wrapper globali o attributi di stub.Iniezione del costruttore del filtro usando Ninject

Con MVC che consente di ignorare quasi tutte le parti del suo funzionamento, avrei pensato che sarebbe stato semplicemente il caso di creare il proprio fornitore di filtri in modo simile a come si crea il proprio risolutore di dipendenze.

Qual è il metodo ora corretto per consentire l'iniezione o diventa più semplice se si utilizzano determinati tipi di filtri o altri?

public class UserValidationAttribute : ActionFilterAttribute 
{ 
    private IRepository repository; 

    public UserValidationAttribute(IRepository repository) 
    { 
     this.repository = repository; 
    } 
} 
+1

Solo una nota: il consenso generale sembra essere che l'iniezione di proprietà debba essere utilizzata per dipendenze opzionali, ma un'iniezione del costruttore per le dipendenze richieste (che tipo di ha senso - non è possibile costruire un tipo senza le sue dipendenze richieste, ma proprietà potrebbe non essere iniettato in base a quali servizi sono disponibili per il contenitore) – Charleh

+0

Ora ho implementato il metodo in cui si dispone di un filtro globale che verifica se si applica controllando se è presente un attributo token. Quello che non ottengo in questo momento è che quando uso l'attributo token sull'azione e utilizzo 'filterContext.ActionDescriptor.IsDefined (typeof (MyTokenAttribute), true)' Ottengo 'true', ma se metto solo il token attributo sul controller ottengo 'false'. –

risposta

2

Supponendo che l'attributo deve essere una parte dei metadati, il che significa che occorre istanziare al compilazione tempo, non è possibile avere un repository iniettato in un attributo da qualsiasi contenitore ioc . I contenitori funzionano in fase di esecuzione.

0

Se si desidera inserire le dipendenze in un filer, si desidera utilizzare l'iniezione di proprietà anziché l'iniezione del costruttore.

public class UserValidationAttribute : ActionFilterAttribute 
{ 
    [Inject] 
    private IRepository repository { get; set; } 

    public UserValidationAttribute() 
    { 
    } 
} 

https://stackoverflow.com/a/7192754/296861

+0

la sua dipendenza è un repository che sembra essere richiesto, quindi dovrebbe essere iniettato tramite costruttore. Inoltre, sento che spruzzare i tuoi attributi magici IoC nelle tue classi è un cattivo schema. La maggior parte dei contenitori IoC oggi supporta l'iniezione nei filtri MVC, inclusi Ninject, Unity v3 e StructureMap –

18

C'è un modo per utilizzare l'iniezione del costruttore.

Per prima cosa è sostituire il vostro attributo con un 'vuoto' quello che si basta usare come marcatore

public class UserValidationAttribute : Attribute { } 

quindi si crea una classe di filtro come un IActionFilter.

public class UserValidationFilter : IActionFilter 
{ 
    private readonly IRepository repository; 

    public UserValidationFilter(IRepository repository) 
    { 
     this.repository = repository; 
    } 

    public void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     //do something 
    } 

    public void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     //do something 
    }  
} 

Poi si può registrare con qualcosa di simile

private static void RegisterServices(IKernel kernel) 
{ 
    kernel.BindFilter<UserValidationFilter>(FilterScope.Action, 0) 
     .WhenActionMethodHas<UserValidationAttribute>(); 
} 

Se l'attributo stessa ha parametri del costruttore, è possibile passare come

kernel.BindFilter<UserValidationFilter>(FilterScope.Action, 0) 
    .WhenActionMethodHas<UserValidationAttribute>(); 
    .WithConstructorArgumentFromActionAttribute<UserValidationAttribute>("myParameter", attr => attr.MyParameter); 

La sintassi BindFilter fa parte di Ninject.Web.Mvc.FilterBindingSyntax.