2009-09-17 12 views
12

Tengo una interfaz como estaStructureMap, constructor que toma una lista de plugins

public interface IWriter 
{ 
    ... 
} 

y una clase

public class WriterMerger 
{ 
    public WriterMerger(IEnumerable<IWriter> writers) 
    ... 
} 

Quiero StructureMap llenar el argumento del constructor en WriterMerger con todas las de iWriter registrados . que registró los diferentes escritores con

StructureMap.ObjectFactory.Initialize(x => 
{ 
    x.ForRequestedType<IWriter>().AddConcreteType<MemoryWriter>(); 
    x.ForRequestedType<IWriter>().AddConcreteType<FlatFileWriter>(); 
    x.ForRequestedType<IWriter>().AddConcreteType<DbWriter>(); 
} 

embargo llamando

ObjectFactory.CreateInstance<WriterMerger>(); 

devuelve una excepción "Sin instancia predeterminada definida para PluginFamily System.Collections.Generic.IEnumerable`1 [[iWriter ..]] " (nombre de clase editado)

¿Algún truco para hacer esto automáticamente? o tendré que hacer un método de fábrica personalizado?

Respuesta

10

Cuando se desea inyectar todos los casos concretos de un tipo, debe declarar el parámetro como una matriz. Puede solucionar el problema cambiando su constructor para:

public WriterMerger(IWriter[] writers) 

tener en cuenta que las herramientas de código de limpieza como ReSharper pueden destacar la matriz en su constructor y le sugerimos que reemplazarlo con IEnumerable, si eso es todo lo que se requiere por su WriterMerger. Sin embargo, estas herramientas no conocen el requisito de StructureMap de utilizar una matriz, por lo que debe ignorarla.

Puede que también le interese saber que puede registrar automáticamente todos sus IWriters, en lugar de enumerarlos explícitamente. Sólo cambia la configuración del contenedor para:

StructureMap.ObjectFactory.Initialize(x => 
{ 
    x.Scan(scan => 
    { 
     scan.TheCallingAssembly(); 
     scan.AddAllTypesOf<IWriter>(); 
    }); 
}); 

Hay un número de diferentes opciones para la exploración que le permiten explorar diferentes montajes, excluir ciertos tipos, etc.

1

Creo que lo que esto te dice es que necesitas definir uno de estos IWriters como el predeterminado. Imagine una clase diferente tenía la siguiente contructor:

public class Test{ 
    public Test(IWriter writer){} 
} 

Sin un defecto iWriter no sabría qué escritor para asignar. Entonces, probablemente necesite decir cuál es el valor predeterminado, incluso si nunca lo usa. Ver este post:

What's the difference between AddConcreteType and TheDefaultIsConcreteType in StructureMap?

2

que duplican su problema y creo que su El código funcionará si cambia su clase de consumo IWriter para tener un controlador que tome una matriz de IWriter.

public class WriterMerger { public WriterMerger(IWriter[] writers) } 

Josh está justo en la hora de recomendar una mejor manera de registrar a todos los tipos de iWriter con StructureMap. Escáneres FTW.

+0

Gracias, que resolvió mi problema – AndreasN

18

En realidad esto se puede hacer sin cambiar su constructor

Cambiar la configuración del contenedor a:

StructureMap.ObjectFactory.Initialize(x => 
{ 
    x.Scan(scan => 
    { 
     scan.TheCallingAssembly(); 
     scan.AddAllTypesOf<IWriter>(); 
    }); 
    x.ForRequestedType<IEnumerable<IWriter>>() 
     .TheDefault.Is.ConstructedBy(x => ObjectFactory.GetAllInstances<IWriter>()); 
}); 
+0

Si bien esto requiere un poco más especificación, este enfoque es menos acoplado a Requisito de StructureMap de especificar la colección como una matriz y, por lo tanto, obtiene un +1 de mí. –

+0

Para aquellos que usan SM3 parece que 'ForRequestedType <>' ha sido eliminado. –

+0

No he usado SM por un tiempo, pero creo que ForRequestedType <> ahora es solo para < –

Cuestiones relacionadas