2009-01-15 4 views
17

Prendere il seguente programma inutile:Risoluzione classi senza registrarti usando il Castello di Windsor

class Program 
{ 
    static void Main(string[] args) 
    { 
     IUnityContainer unityContainer = new UnityContainer(); 
     IWindsorContainer windsorContainer = new WindsorContainer(); 

     Program unityProgram = unityContainer.Resolve<Program>(); 
     Program castleProgram = windsorContainer.Resolve<Program>(); 
    } 
} 

L'UnityContainer mi restituirà un'istanza di programma, dove, come il contenitore di Windsor getterà un ComponentNotFoundException.

Sono in grado di visualizzare gli argomenti per entrambi i comportamenti e non mi dispiace quale sia la fine, tuttavia Prism V2 Drop 8 (l'ultimo al momento della scrittura) si basa sul comportamento di Unity internamente, richiedendo classi che non sono state registrate .

Anziché trovare e registrare tutte queste classi per Prism, preferirei che Windsor si comportasse come Unity. Non ho trovato nulla su google per aiutarmi a fare questo (anche se la mia terminologia potrebbe essere sbagliata) e la documentazione di Windsor è piuttosto scadente ...

Qualcuno può suggerire una soluzione a questo problema?

+1

non fa questo genere di sconfitta lo scopo di un IoC? Se aveste risolto IProgram, troverebbe una definizione di classe che implementa IProgram in quel caso? – jishi

+0

Immagino che tu ottenga ancora il vantaggio dell'iniezione di dipendenza sulla classe anche se non usi un'interfaccia. –

+3

jishi: le risposte alle tue domande sono no e no. No, non sconfigge lo scopo di IoC. No, non mappa le interfacce senza che siano registrate. – Anthony

risposta

9

Windsor attualmente non supporta questo ed è di progettazione. Il ragionamento è che dovresti registrare esplicitamente i tipi di cui hai bisogno in modo che tu non abbia un oggetto mal configurato.

Esiste tuttavia la possibilità che venga aggiunto un hook per creare un tipo non registrato in un determinato momento nel prossimo futuro, poiché ciò è necessario per la funzione di integrazione WCF. (Edit - è stato aggiunto in v2.1 - dare un'occhiata a ILazyComponentLoader s)

Comunque, indipendentemente caricatori componenti pigri, il meglio che puoi fare è usare API fluente a lotto registrare tutti i tipi da un assembly abbinare i criteri necessari in anticipo. Non è molto più codice e dormirai meglio di notte.

Utilizzare i caricatori pigri solo se non si dispone di informazioni sufficienti all'avvio (nella radice di composizione ) per determinare quali componenti sono necessari.

+0

Perché il dispositivo di integrazione WCF di Windsor deve creare tipi non registrati? – urig

+3

@urig: in questo modo è possibile pronunciare solo i tipi specificati nel proprio file web.config e non duplicare la registrazione nel contenitore. ASCIUTTO. –

6

Windsor non supporta che fuori dalla scatola, ma è possibile creare metodi di estensione per farlo:

static class WindsorExtensions 
{ 
    public static object ResolveType(this IWindsorContainer container, Type type) 
    { 
     if (type.IsClass && !container.Kernel.HasComponent(type)) 
      container.Kernel.AddComponent(type.FullName, type, LifestyleType.Transient); 
     return container.Resolve(type); 
    } 

    public static T ResolveType<T>(this IWindsorContainer container) 
    { return (T)ResolveType(container, typeof(T)); } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IUnityContainer unityContainer = new UnityContainer(); 
     IWindsorContainer windsorContainer = new WindsorContainer(); 

     Program unityProgram = unityContainer.Resolve<Program>(); 
     Program castleProgram = windsorContainer.ResolveType<Program>(); 
    } 
} 
+0

Questo non duplica completamente la funzionalità se Unity: solo la classe di livello superiore verrà registrata automaticamente. Cosa succede se la classe A dipende dalla classe B concreta, né A o B sono registrati e si tenta di risolvere A? Unity gestirà questo, ma il tuo codice sopra non lo farà. – Anthony

+0

Questo è vero.Tuttavia, in tutti i casi in cui dovevo risolvere un tipo non registrato, non ho mai avuto bisogno della risoluzione "ricorsiva" di altre dipendenze non registrate che descrivi. Dovrebbe essere possibile implementarlo anche su Windsor, ma personalmente non ne avevo bisogno. –

2

Krzysztof non abbiate paura di link al tuo blog qui :) http://devlicious.com/blogs/krzysztof_kozmic/archive/2009/11/16/castle-windsor-lazy-loading.aspx

Inoltre, ho trovato questa semplice applicazione utile nel mio WPF app, rimuovere il contraint corda e si è vicino al caso generale

public class ViewModelLoader : Castle.MicroKernel.Resolvers.ILazyComponentLoader { 
    public IRegistration Load(string key, Type service) 
    { 
     if (service == null) 
      return null; 
     if (service.Name.EndsWith("ViewModel", StringComparison.CurrentCultureIgnoreCase)) 
      return Component.For(service).Named(key); 
     else 
      return null; 
    } 
}