2009-06-23 2 views

risposta

1

si hanno due opzioni

La prima opzione è quella di scrivere un ActionInvoker personalizzato, che non è così difficile come sembra. Dai un'occhiata a questo blog post. Si occupa in modo specifico di NInject, ma Unity supporta l'iniezione di proprietà in modo da poter modificare l'esempio per utilizzare Unity.

Questa è l'opzione che accoppia il contenitore IoC e non è consigliato.

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

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

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

ho tentato la soluzione trovata nel post del blog, ma sembra che ci sia alcune differenze tra l'Unità e Ninject, oppure da qualche parte, il codice di qualcuno è sbagliato :). I filtri sono in sola lettura quando raggiungono "InvokeExceptionFilters" sovrascritto. Quindi posso dichiarare un nuovo filtro e iniettare dipendenze, ma se provo a iniettare dipendenze dall'elenco fornito di ExceptionFilters, non succede nulla. Potrei creare un nuovo filtro e passarlo alla classe base, ma poi perderei tutte le informazioni dichiarative fornite sull'attributo stesso. –

2

Ok, ho capito.

Principalmente ho usato la soluzione di Ben sopra dal post del blog che ha indicato.

Il problema è che Unity si comporta in modo leggermente diverso.

Non è possibile iniettare direttamente dipendenze dai filtri, poiché sono rispettivamente di tipo IActionFilter e IExceptionFilter. Questo mi ha portato a credere che fossero di sola lettura, il che non è così. È solo che Unity deve conoscere il tipo esplicito per iniettare.

Quindi, nel metodo sottoposto a override fornito dall'articolo, gli utenti Unity devono interrogare i filtri per i tipi in questione e quindi costruirli.

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

E poi nel metodo override, fare qualcosa di simile:

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

un po 'disordinato, ma ha solo bisogno di essere fatto una volta, e mantiene tutto disaccoppiato come suggerisce Ben.

L'altro trucco è che non è possibile chiamare _container.BuildUp (filtro) all'interno di un ciclo foreach, perché il filtro è in sola lettura in quel contesto.

1

Anche io ho riscontrato questo problema e ora ho una soluzione funzionante. È simile alla soluzione sopra descritta ma con alcune leggere differenze e anche con il codice Unity completo aggiunto.

Per prima cosa utilizzerò l'iniezione di proprietà per la ragione sopra descritta e, come sopra, userò il metodo BuildUp su Unity per iniettare le proprietà nei filtri già creati.

Per fare ciò ho ereditato tutti i controller da una nuova classe di base personalizzata. Su quella classe base sovrascrivo il metodo CreateActionInvoker per impostare il mio ActionInvoker personalizzato.

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

Quindi nel mio CustomActionInvoker sovrascrivo il metodo 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 

Contrariamente a quanto detto sopra non ho trovato che facendo l'accumulo all'interno di un ciclo For Each causato problemi.Ho anche superato il problema originale di avere solo l'oggetto referenziato tramite un'interfaccia utilizzando uno degli altri overload del metodo BuildUp che accetta un System.Type così come l'oggetto esistente.

Con tutte le operazioni precedenti, ora posso iniettare direttamente le dipendenze nei miei filtri.

Qualsiasi commento e pensiero molto apprezzato.

Acclamazioni Mike