2009-11-17 3 views
6

Da lungo tempo il lettore prima volta scrittore qui. Attualmente sto facendo una conversione dall'uso di Ninject all'attuale versione di Castle Windsor per una semplice applicazione C# .NET.Castello di Windsor: un problema con costruttori più

Per la maggior parte, la conversione è andato bene e l'attuazione dei contenitori è eseguito perfettamente. Sto comunque avendo un piccolo problema con i miei oggetti repository.

Ho un oggetto repository utente che è codificato nel modo seguente:

public class UserRepository : IUserRepository { 
    public UserRepository(IObjectContext objectContext) { 
     // Check that the supplied arguments are valid. 
     Validate.Arguments.IsNotNull(objectContext, "objectContext"); 

     // Initialize the local fields. 
     ObjectContext = objectContext; 
    } 

    public UserRepository(IObjectContextFactory factory) 
     : this(factory.CreateObjectContext()) { 
    } 

    // ----------------------------------------------- 
    // Insert methods and properties... 
    // ----------------------------------------------- 
} 

Per corrispondere a questo codice, ho impostare le seguenti voci nel file di configurazione di mia domanda:

<castle> 
    <components> 
     <component id="objectContextFactory" lifestyle="custom" 
        customLifestyleType="Common.Infrastructure.PerWebRequestLifestyleManager, Common.Castle" 
        service="Project.DAL.Context.IObjectContextFactory, Project.DAL.LINQ" 
        type="project.DAL.Context.ObjectContextFactory, Project.DAL.LINQ"> 
     </component> 
     <component id="userRepository" lifestyle="custom" 
        customLifestyleType="Common.Infrastructure.PerWebRequestLifestyleManager, Common.Castle" 
        service="Project.BL.Repository.IUserRepository, Project.BL" 
        type="Project.BL.Repository.UserRepository, Project.BL.LINQ"> 
      <parameters> 
       <factory>${objectContextFactory}</factory> 
      </parameters> 
     </component> 
    </components> 
</castle> 

Per me, tutto sembra come dovrebbe. Quando si tenta di risolvere un'istanza del servizio IObjectContextFactory, posso recuperare un oggetto ObjectContextFactory. Il mio problema arriva quando provo a risolvere un'istanza del servizio IUserRepository. Sono soddisfatto della seguente deliziosa eccezione:

Impossibile creare il componente 'userRepository' in quanto ha dipendenze da soddisfare. UserRepository sta aspettando le seguenti dipendenze:

Servizi:

- SandCastle.DAL.Context.IObjectContext which was not registered.

Ho provato tutto quello che posso pensare a questo. Quindi, per voi lettori di stackoverflow, dico: avete qualche idea?

risposta

7

Questo potrebbe essere considerato come un bug (e in effetti per casi come questo è risolvibile), ma si tratta di una caratteristica di kindof by design.

Windsor cerca di far corrispondere il costruttore più golosi (quello con la maggior parte dei parametri) può soddisfare.

Tuttavia nel tuo caso, ci sono due costruttori che hanno il maggior numero di parametri (di uno), quindi Windsor sceglie solo il primo, dove ciò che il "primo" significa non è definito.

in effetti se si passa l'ordine dei costruttori nel codice sorgente il codice inizierà a funzionare, anche se si tratta di un trucco, basandosi su un comportamento non documentato e non farlo.

Torniamo al punto di partenza che ne dite?

Ho detto che Windsor è confuso perché non c'è il single il costruttore più avido che possa soddisfare.

soluzione rapida e ben definito potrebbe essere quella di aggiungere un parametro falso per uno dei costruttori th in modo che abbiano un diverso numero di parametri:

public class UserRepository : IUserRepository { 
    public UserRepository(IObjectContext objectContext, object fakeIgnoreMe) { 
     // Check that the supplied arguments are valid. 
     Validate.Arguments.IsNotNull(objectContext, "objectContext"); 
     // ignoring fake additional argument 
     // Initialize the local fields. 
     ObjectContext = objectContext; 
    } 

    public UserRepository(IObjectContextFactory factory) 
     : this(factory.CreateObjectContext()) { 
    } 

    // ----------------------------------------------- 
    // Insert methods and properties... 
    // ----------------------------------------------- 
} 

Si prega di segnalare questo problema a Castle users list o straight to issue tracker in modo che lo farà sistemati

+0

Ha lavorato come gangbusters! Grazie! – highvoltage

+2

"Windsor cerca di abbinare il costruttore più avido (uno con il maggior numero di parametri che può soddisfare)". Penso che sia più corretto dire "dalla lista dei costruttori che contengono solo parametri risolvibili, viene scelto il costruttore con il maggior numero di parametri". – Steven

+0

@Steven che ne dici adesso? –

0

A partire da Windsor 3.2.x

Se l'attributo Castle.Core.DoNotSelectAttribute viene applicato a un costruttore, non sarà selezionato, nonostante qualsiasi altro criterio.

public class UserRepository : IUserRepository 
{ 
    [DoNotSelect] // This constructor will be ignored by Windsor 
    public UserRepository(IObjectContext objectContext) 
    { 
     // ... 
    } 

    public UserRepository(IObjectContextFactory factory) 
     : this(factory.CreateObjectContext()) {} 
} 

Riferimento: https://github.com/castleproject/Windsor/blob/86696989a7698c45b992eb6e7a67b765b48108b0/docs/how-constructor-is-selected.md