2009-11-17 12 views
6

Lector de primera vez escritor por primera vez aquí. Actualmente estoy llevando a cabo una conversión desde el uso de Ninject hasta el lanzamiento actual de Castle Windsor para una simple aplicación C# .NET.Castle Windsor: Problema con varios constructores

En su mayor parte, la conversión ha ido bien y la implementación de los contenedores se ha ejecutado sin problemas. Sin embargo, tengo un pequeño problema con mis objetos de repositorio.

que tienen un objeto repositorio de usuarios que se codifica de la siguiente manera:

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... 
    // ----------------------------------------------- 
} 

Para corresponder a este código, he fijado las siguientes entradas en el archivo de configuración de mi solicitud:

<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> 

Para mí, todo parece que debería. Cuando intento resolver una instancia del servicio IObjectContextFactory, recupero un objeto ObjectContextFactory. Mi problema aparece cuando intento resolver una instancia del servicio IUserRepository. Me tratan las siguientes deliciosas excepciones:

No se puede crear el componente 'userRepository' ya que tiene dependencias que cumplir. userRepository está esperando por las siguientes dependencias:

Servicios:

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

He intentado todo lo que puedo pensar en esto. Entonces, para ustedes lectores de stackoverflow, les digo: ¿tengo alguna idea?

Respuesta

7

Esto podría ser considerado como un error (y de hecho, en casos como este se puede corregir), pero es una especie de característica de diseño.

Windsor intenta hacer coincidir el constructor más codicioso (uno con la mayoría de los parámetros) que puede satisfacer.

Sin embargo, en su caso, hay dos constructores que tienen la mayor cantidad de parámetros (de uno), por lo que Windsor simplemente elige el primero, donde lo que significa "el primero" no está definido.

De hecho, si cambia el orden de sus constructores en su código fuente, su código comenzará a funcionar, aunque es un truco, dependiendo del comportamiento no documentado y no lo haga.

Volvamos a donde empezamos ¿o sí?

Dije que Windsor está confundido porque no hay único constructor más codicioso que pueda satisfacer.

Solución rápida y bien definida sería añadir un parámetro falso para uno de th constructores para que tengan diferente número de parámetros:

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... 
    // ----------------------------------------------- 
} 

informa de esta incidencia a Castle users list o straight to issue tracker que para que quiera arreglarse

+0

Trabajado como frenética! ¡Gracias! – highvoltage

+2

"Windsor intenta hacer coincidir el constructor más codicioso (uno con la mayoría de los parámetros que puede satisfacer)". Creo que es más correcto decir "de la lista de constructores que solo contienen parámetros resolubles, se selecciona el constructor con más parámetros". – Steven

+0

@Steven ¿y ahora? –

0

As of Windsor 3.2.x

Si el atributo Castle.Core.DoNotSelectAttribute se aplica a un constructor, no se seleccionará, independientemente de cualquier otro criterio.

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

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

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

Cuestiones relacionadas