Domanda

Ho un'interfaccia come questa

public interface IWriter
{
  ...
}

e una classe

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

Voglio che Structuremap compili l'argomento del costruttore su WriterMerger con tutti gli IWriter registrati. Ho registrato i diversi scrittori con

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

comunque chiamando

ObjectFactory.CreateInstance<WriterMerger>();

Restituisce un'eccezione " Nessuna istanza predefinita definita per PluginFamily System.Collections.Generic.IEnumerable`1 [[IWriter ..]] " (nome classe modificato)

Qualche trucco per farlo automaticamente? o dovrò creare un metodo di fabbrica personalizzato?

È stato utile?

Soluzione

Quando si desidera iniettare tutte le istanze concrete di un tipo, è NECESSARIO dichiarare il parametro come un array. Puoi risolvere il tuo problema cambiando il costruttore in:

public WriterMerger(IWriter[] writers)

Tieni presente che gli strumenti di pulizia del codice come ReSharper possono evidenziare l'array nel tuo costruttore e suggerirti di sostituirlo con IEnumerable, se questo è tutto ciò che è richiesto da WriterMerger. Tuttavia, questi strumenti non sono a conoscenza del requisito di StructureMap di utilizzare un array, quindi è necessario ignorarlo.

Potresti anche essere interessato a sapere che puoi registrare automaticamente tutti i tuoi IWriter, invece di elencarli esplicitamente. Cambia la configurazione del tuo contenitore in:

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

Esistono diverse opzioni di scansione che consentono di scansionare assiemi diversi, escludere determinati tipi, ecc.

Altri suggerimenti

In realtà questo può essere fatto senza cambiare il costruttore

Cambia la configurazione del tuo contenitore in:

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

Ho duplicato il tuo problema e credo che il tuo codice funzionerà se cambi la tua classe che consuma IWriter per avere un ctor che prende una matrice di IWriter.

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

Josh ha ragione nel raccomandare un modo migliore per registrare tutti i tipi di IWriter con StructureMap. Scanner FTW.

Penso che ciò che ti sta dicendo sia che devi definire uno di questi IWriter come predefinito. Immagina che una classe diversa avesse il seguente costruttore:

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

Senza un IWriter predefinito non sarebbe in grado di sapere quale scrittore assegnare. Quindi probabilmente dovrai dire qual è il valore predefinito anche se non lo usi mai. Vedi questo post:

Qual è la differenza tra AddConcreteType e TheDefaultIsConcreteType in StructureMap? / a>

scroll top