Frage

Ich bin gerade erst anfangen mit DI & Unit-Tests und haben einen Haken getroffen, die ich sicher bin, ist ein Klacks für die erfahreneren Devs:

Ich habe eine Klasse namens Messagemanager, die Daten empfängt und speichert sie in einer db. Innerhalb der gleichen Anordnung (Projekt in Visual Studio) Ich habe eine Repository-Schnittstelle mit allen Methoden erstellt benötigt, um die DB zugreifen. Die konkrete Umsetzung dieser Schnittstelle ist in einer separaten Assembly namens Data Access.

So Data Access einen Projektverweis auf Messagemanager muss über die Repository-Schnittstelle kennen. Und Messagemanager muss einen Projektverweis auf Data Access, so dass der Kunde von Messagemanager eine konkrete Umsetzung der Repository-Schnittstelle injizieren. Dies ist von courser nicht erlaubt

Ich kann die Schnittstelle in die Datenzugriffsanordnung bewegen, aber ich glaube, dass die Repository-Schnittstelle gemeint ist, in der gleichen Anordnung wie der Client befindet, die es verwendet

Also, was habe ich falsch gemacht?

War es hilfreich?

Lösung

Verwenden Sie eine Inversion of Control Container? Wenn ja, ist die Antwort einfach.

Assembly A enthält:

  • Messagemanager
  • IRepository
  • ContainerA (add Messagemanager)

Assembly B enthält (und ref des AssemblyA):

  • Repository implementiert IRepository
  • ContainerB erweitert ContainerA (Add Repository)

Montage C (oder B) würde die App starten / bitten, den Behälter für die Messagemanager würde wissen, wie Messagemanager lösen und die IRepository.

Andere Tipps

Sie sollten Ihre Schnittstelle aus beiden Montage trennen. Setzen Sie die Schnittstelle zusammen mit dem Verbraucher oder Implementierer Niederlagen den Zweck die Schnittstelle zu haben.

Der Zweck der Schnittstelle ist, damit Sie ein beliebiges Objekt injizieren, die diese Schnittstelle implementiert, ob oder nicht, es ist die gleiche Anordnung, die Ihr Data Access-Objekt gehört. Auf der anderen Seite müssen Sie Messagemanager verbrauchen diese Schnittstelle ohne die Notwendigkeit, damit eine konkrete Umsetzung zu konsumieren.

Setzen Sie Ihre Schnittstelle in einem anderen Projekt, und Problem gelöst ist.

Sie haben nur zwei Möglichkeiten: in eine Baugruppe, die Schnittstelle zu halten oder die Schnittstelle in die Data Access Montage zu bewegen. Selbst wenn Sie eine Architektur sind zu entwickeln, wo die Data Access Klasse eines Tages von einem anderen Implementierer (auch in einer anderen Assembly) der Repository-Schnittstelle ersetzt werden kann, gibt es keinen Grund, sie aus der Data Access Montage auszuschließen.

Ich denke, man sollte die Repository-Schnittstelle über auf die Data Access Montag bewegen. Dann hat Data Access keine Notwendigkeit Messagemanager zu verweisen mehr.

Allerdings bleibt es schwer zu sagen, da ich nichts über Ihre Architektur weiter weiß ...

Häufig können Sie Kreisreferenz Probleme lösen, indem Sie Setter Injektion statt Konstruktor Injektion.

In Pseudo-Code:

Foo f = new Foo();
Bar b = new Bar();
f.setBar(b);
b.setFoo(f);

Inversion Abhängigkeit im Spiel ist:

High Level-Module soll nicht auf niedrigem Niveau Module ab. Beide sollten auf Abstraktionen abhängen. Abstraktionen sollten sich nicht auf Details abhängen. Details sollten auf Abstraktionen abhängen.

Die Abstraktion, die die Klassen in der DatAccess Montage auf Bedürfnisse hängen in einer separaten Assembly von den Data Access-Klassen und der konkreten Umsetzung dieser abstration (Messagemanager) sein.

Ja, das ist mehr Baugruppen. Persönlich ist das keine große Sache für mich. Ich habe keinen großen Nachteil in zusätzlichen Baugruppen sehen.

Sie können die Struktur verlassen, wie Sie es derzeit haben (ohne die Abhängigkeit von Messagemanager zu Data Access, die das Problem verursacht) und haben dann MessageManager dynamisch die konkrete Implementierung zur Laufzeit benötigt laden die System.Reflection.Assembly-Klasse.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top