Pergunta

Eu tenho uma interface como este

public interface IWriter
{
  ...
}

e uma classe

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

Eu quero StructureMap para preencher o argumento do construtor em WriterMerger com todas nominativas iWriter de. Registei-me os diferentes escritores com

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

No entanto chamando

ObjectFactory.CreateInstance<WriterMerger>();

Retorna uma exceção "Não Padrão Instância definido para PluginFamily System.Collections.Generic.IEnumerable`1 [[iWriter ..]]" (nome da classe editado)

Qualquer truque para fazer isso automaticamente? ou eu vou ter que fazer um método de fábrica personalizado?

Foi útil?

Solução

Quando você quer todas as instâncias concretas de um tipo para ser injetado, você deve declarar o parâmetro como uma matriz. Você pode resolver o problema alterando o seu construtor para:

public WriterMerger(IWriter[] writers)

Esteja ciente de que ferramentas de limpeza de código como ReSharper pode realçar a matriz em seu construtor e sugerir-lhe substituí-lo com IEnumerable, se isso é tudo o que é exigido pelo seu WriterMerger. No entanto, essas ferramentas não estão cientes da necessidade de StructureMap usar uma matriz, então você tem que ignorá-lo.

Você também pode estar interessado em saber que você pode registrar automaticamente todos os seus IWriters, em vez de listá-los explicitamente. Basta alterar a configuração do recipiente para:

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

Há uma série de opções diferentes de digitalização que permitem digitalizar diferentes montagens, excluir determinados tipos, etc.

Outras dicas

Na verdade, isso pode ser feito sem alterar o construtor

Mude sua configuração recipiente para:

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

Eu dupliquei o seu problema e eu acredito que o código irá funcionar se você mudar de iWriter consumindo classe para ter um ctor que leva uma série de iWriter.

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

Josh está certo sobre em recomendar a melhor maneira de registrar todos os tipos de iWriter com StructureMap. Scanners FTW.

Eu acho que isso está lhe dizendo é que você precisa para definir um desses IWriters como padrão. Imagine uma classe diferente teve o seguinte contructor:

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

Sem um padrão iWriter não saberia qual escritor atribuir. Então você provavelmente terá que dizer que é o padrão, mesmo se você nunca user-lo. Veja este post:

Qual é a diferença entre AddConcreteType e TheDefaultIsConcreteType em StructureMap?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top