Como uso o StructureMap com tipos não fechados genéricos usando o Scan com um construtor "ganancioso"
Entre várias perguntas do Stack Overflow e postagens do blog, há uma quantidade bastante razoável de documentação sobre o tópico de genéricos abertos e o StructureMap. Infelizmente, devo estar faltando alguma coisa, pois minhas tentativas de usarscan
para executar a configuração, juntamente com uma implementação de classe que tenha um construtor "ganancioso", ainda funcionam.
Eu quero que o StructureMap pegue uma instância da classe abaixo por meio de referências à sua interface implementada.ToCsvService
existe em um assembly não referenciado chamado Infraestrutura.IToCsvService
existe em um assembly referenciado chamado Core. Como você pode verToCsvService
tem um construtor "ganancioso".
public class ToCsvService<TSource> : IToCsvService<TSource>
{
public ToCsvService(ICollection<TSource> collection)
{
}
}
Informei o StructureMap sobreToCsvService
através doConnectImplementationsToTypesClosing
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<>));
});
});
DeObjectFactory.WhatDoIHave()
método parece que o StructureMap está ciente 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
No entanto, quando eu especificarIToCsvService<CustomerViewModel>
em um construtor Controller, lança a exceção
Código de exceção do StructureMap: 202 Nenhuma instância padrão definida para PluginFamily Core.Services.IToCsvService`1 [[UI.Models.MachineForm, UI, Versão = 1.0.0.0, Cultura = neutra, PublicKeyToken = null]], Core, Versão = 1.0. 0.0, Cultura = neutro, PublicKeyToken = nulo
Eu imagino que isso ocorre porque o StructureMap não tem idéia do que entregar o "ganancioso"ToCsvService
construtor. Existe alguma maneira de tornar o StructureMap capaz de funcionar bem com esse construtor? Preciso mudar de um construtor e apenas definir a propriedade de coleção após a instanciação?
A questãoMapa de estrutura e tipos genéricos detalhes que estou tentando fazer, mas não utiliza uma digitalização para fazer isso. oresponda fornecido porJoshua Flanagan utiliza oFor(x).Use(y)
configuração, que pode funcionar se eu não estiver varrendo a montagem porque não tenho uma referênciaToCsvService
.
Editar
Eu queria ver se estava usando um mecanismo diferente para permitir que o StructureMap identificasse instâncias deToCsvService<>
teria um efeito. Ele muda o que é relatado emObjectFactory.WhatDoIHave()
e lança uma exceção diferente. Aqui está um exemplo de usoAddAllTypesOf
.
ObjectFactory.Initialize(cfg =>
{
cfg.Scan(scan =>
{
scan.Assembly("Infrastructure");
scan.WithDefaultConventions();
scan.AddAllTypesOf(typeof(IToCsvService<>));
});
});
Depois de usar o acima, o despejo deObjectFactory.WhatDoIHave()
é
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
Com esta configuração, lancei esta exceção:
Código de exceção do StructureMap: 202 Nenhuma instância padrão definida para PluginFamily System.Collections.Generic.ICollection`1 [[UI.Models.MachineForm, UI, Versão = 1.0.0.0, Cultura = neutra, PublicKeyToken = null]], mscorlib, Versão = 4.0.0.0, Cultura = neutra, PublicKeyToken = b77a5c561934e089
Para mim, a exceção indica que o StructureMap sabe que precisa de umICollection<MachineForm>
instanciarToCsvService
mas não sabe de onde obtê-lo. Que vai paraJimmy's comentar abaixo sobre o uso do StructureMap eInjeção de setter de construtor. No entanto, isso não parece possível sem adicionar uma referência explícita ao assembly Infraestrutura.