12 Stimmen

Structuremap, Konstruktor, der eine Liste von Plugins annimmt

Ich habe eine Schnittstelle wie diese

public interface IWriter
{
  ...
}

und eine Klasse

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

Ich möchte, dass structuremap das Konstruktorargument bei WriterMerger mit allen registrierten IWritern ausfüllt. Ich habe die verschiedenen Writer mit

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

aber der Aufruf

ObjectFactory.CreateInstance<WriterMerger>();

Gibt eine Ausnahme zurück "Keine Standardinstanz definiert für PluginFamily System.Collections.Generic.IEnumerable`1[[IWriter..]]" (Klassenname bearbeitet)

Gibt es einen Trick, um dies automatisch zu tun, oder muss ich eine benutzerdefinierte Fabrikmethode erstellen?

18voto

Evil Andy Punkte 1702

Eigentlich kann man dies tun, ohne den Konstruktor zu ändern

Ändern Sie Ihre Containerkonfiguration in:

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

0 Stimmen

Dies erfordert zwar etwas mehr Spezifikation, aber dieser Ansatz ist weniger an die StructureMap-Anforderung gekoppelt, die Sammlung als Array zu spezifizieren, und erhält daher von mir ein +1.

0 Stimmen

Für diejenigen, die SM3 verwenden, sieht es so aus ForRequestedType<> wurde entfernt.

0 Stimmen

Ich habe SM schon eine Weile nicht mehr benutzt, aber ich glaube, ForRequestedType<> ist jetzt einfach For<>

10voto

Joshua Flanagan Punkte 8478

Wenn Sie wollen, dass alle konkreten Instanzen eines Typs injiziert werden, MÜSSEN Sie den Parameter als Array deklarieren. Sie können Ihr Problem beheben, indem Sie Ihren Konstruktor zu ändern:

public WriterMerger(IWriter[] writers)

Beachten Sie, dass Codebereinigungstools wie ReSharper das Array in Ihrem Konstruktor hervorheben und vorschlagen können, es durch IEnumerable zu ersetzen, wenn dies alles ist, was von Ihrem WriterMerger benötigt wird. Diese Tools sind sich jedoch nicht bewusst, dass StructureMap ein Array verwenden muss, so dass Sie dies ignorieren müssen.

Vielleicht interessiert es Sie auch, dass Sie alle Ihre IWriters automatisch registrieren können, anstatt sie explizit aufzulisten. Ändern Sie einfach Ihre Container-Konfiguration in:

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

Es gibt eine Reihe verschiedener Optionen für das Scannen, mit denen Sie verschiedene Baugruppen scannen, bestimmte Typen ausschließen können usw.

2voto

KevM Punkte 2426

Ich habe Ihr Problem dupliziert und ich glaube, dass Ihr Code funktionieren wird, wenn Sie Ihre IWriter verbrauchende Klasse ändern, um einen Ctor zu haben, der ein Array von IWriter nimmt.

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

Josh hat Recht, wenn er eine bessere Methode zur Registrierung aller IWriter-Typen mit StructureMap empfiehlt. Scanner FTW.

1voto

Michael Edwards Punkte 5878

Ich denke, das bedeutet, dass Sie einen dieser IWriters als Standard definieren müssen. Stellen Sie sich vor, eine andere Klasse hätte den folgenden Konstruktor:

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

Ohne einen Standard-IWriter wüsste es nicht, welchen Autor es zuweisen soll. Sie müssen also wahrscheinlich angeben, welcher der Standardschreiber ist, auch wenn Sie ihn nie benutzen. Siehe diesen Beitrag:

Was ist der Unterschied zwischen AddConcreteType und TheDefaultIsConcreteType in StructureMap?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X