¿Cómo uso StructureMap con tipos genéricos no cerrados usando Scan con un constructor "codicioso"?
Entre varias preguntas de Stack Overflow y publicaciones de blog hay una cantidad bastante razonable de documentación sobre el tema de los genéricos abiertos y StructureMap. Desafortunadamente, me falta algo como mis intentos de usarscan
para realizar la configuración junto con una implementación de clase que tiene un constructor "codicioso" todavía funciona.
Quiero que StructureMap tome una instancia de la clase a continuación a través de referencias a su interfaz implementada.ToCsvService
existe en un ensamblado sin referencia llamado Infraestructura.IToCsvService
existe en un ensamblado referenciado llamado Core. Como puedes verToCsvService
tiene un constructor "codicioso".
public class ToCsvService<TSource> : IToCsvService<TSource>
{
public ToCsvService(ICollection<TSource> collection)
{
}
}
Dejo que StructureMap sepa sobreToCsvService
mediante elConnectImplementationsToTypesClosing
método.
ObjectFactory.Initialize(cfg =>
{
cfg.Scan(scan =>
{
scan.Assembly("Infrastructure");
scan.WithDefaultConventions();
// even with this call StructureMap cannot use ToCsvService
// instance of IToCsvService (though wouldn't expect it to)
scan.ConnectImplementationsToTypesClosing
(typeof(IToCsvService<>));
});
});
Desde elObjectFactory.WhatDoIHave()
método parece que StructureMap es consciente deToCsvService
.
PluginType Name Description ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ IToCsvService`1 (IToCsvService`1) Scoped as: Transient 6202a7ee-89a4-4edd-831d-4867b7dd1a7e Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Sin embargo cuando especificoIToCsvService<CustomerViewModel>
en un constructor Controlador arroja la excepción
Código de excepción de StructureMap: 202 Sin instancia predeterminada definida para PluginFamily Core.Services.IToCsvService`1 [[UI.Models.MachineForm, UI, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]], Core, Version = 1.0. 0.0, Cultura = neutral, PublicKeyToken = nulo
Me imagino que esto se debe a que StructureMap no tiene idea de qué entregar al "codicioso"ToCsvService
constructor. ¿Hay alguna manera de hacer que StructureMap pueda jugar bien con este constructor? ¿Necesito cambiar de un constructor y simplemente establecer la propiedad de colección después de la creación de instancias?
La preguntaMapa de estructura y tipos genéricos detalles que estoy tratando de hacer, pero no utiliza un escaneo para hacerlo. losresponder proporcionado porJoshua Flanagan utiliza elFor(x).Use(y)
configuración, que podría funcionar si no estuviera escaneando el ensamblaje porque no tengo una referenciaToCsvService
.
Editar
Quería ver si usar un mecanismo diferente para permitir que StructureMap identifique instancias deToCsvService<>
tendría un efecto Cambia lo que se informa enObjectFactory.WhatDoIHave()
y lanza una excepción diferente. Aquí hay un ejemplo de usoAddAllTypesOf
.
ObjectFactory.Initialize(cfg =>
{
cfg.Scan(scan =>
{
scan.Assembly("Infrastructure");
scan.WithDefaultConventions();
scan.AddAllTypesOf(typeof(IToCsvService<>));
});
});
Después de usar lo anterior, el volcado deObjectFactory.WhatDoIHave()
es
PluginType Name Description -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- IToCsvService`1 (IToCsvService`1) Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Scoped as: Transient Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- IToCsvService`1 (IToCsvService`1) Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Scoped as: Transient Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Con esta configuración lanzo esta excepción:
Código de excepción de StructureMap: 202 Sin instancia predeterminada definida para PluginFamily System.Collections.Generic.ICollection`1 [[UI.Models.MachineForm, UI, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]], mscorlib, Version = 4.0.0.0, Cultura = neutral, PublicKeyToken = b77a5c561934e089
Para mí, la excepción indica que StructureMap sabe que necesita unICollection<MachineForm>
instanciarToCsvService
pero no sabe de dónde obtenerlo. Que va aJimmy's comente a continuación sobre el uso de StructureMap yInyector de constructor setter. Sin embargo, esto no parece posible sin agregar una referencia explícita al ensamblaje de Infraestructura.