Frage

Ich verwende C# mit Microsofts Unity Framework. Ich bin mir nicht ganz sicher, wie ich dieses Problem lösen soll. Es hat wahrscheinlich etwas mit meinem mangelnden Verständnis von DI mit Einheit zu tun.

Mein Problem kann mit dem folgenden Beispielcode zusammengefasst werden:

class Train(Person p) { ... }

class Bus(Person p) { ... }

class Person(string name) { ... }

Person dad = new Person("joe");
Person son = new Person("timmy");

Wenn ich die Resolve -Methode im Bus anrufe, wie kann ich sicher sein, dass die Person mit dem Namen "Timmy" injiziert wird und bei der Auflösung des Zuges ich sicher sein kann, dass diese Person "Papa" mit dem Namen "Joe" gelöst ist?

Ich denke, benutze vielleicht genannte Instanzen? Aber ich bin ratlos. Jede Hilfe wäre geschätzt.

Abgesehen davon würde ich lieber keine iPerson -Schnittstelle erstellen.

War es hilfreich?

Lösung

Eine Möglichkeit, dies zu lösen, wäre die Verwendung eines Injektionskonstruktors mit einer benannten Registrierung.

// Register timmy this way  
Person son = new Person("Timmy");  
container.RegisterInstance<Person>("son", son);  

// OR register timmy this way  
container.RegisterType<Person>("son", new InjectionConstructor("Timmy"));  

// Either way, register bus this way.  
container.RegisterType<Bus>(new InjectionConstructor(container.Resolve<Person>("son")));  

// Repeat for Joe / Train

Andere Tipps

Wenn Sie sich nicht als "Joe" und "Timmy" als Abhängigkeiten registrieren, können Sie nicht sicher sein, dass "Timmy" in Schoolbus injiziert wird. Wenn Sie versuchen, zwei Instanzen derselben Klasse wie unbenannte Abhängigkeiten zu registrieren, haben Sie ein mehrdeutiges Setup und können nicht beheben können Person überhaupt.

Wenn Sie im Allgemeinen viele benannte Fälle registrieren müssen, gehen Sie wahrscheinlich DI auf die falsche Weise. Die Hauptidee von DI ist die Lösung Domänendienste mehr als Domänenobjekte.

Die Hauptidee von DI besteht darin, einen Mechanismus bereitzustellen, der es Ihnen ermöglicht, aufzulösen abstrakte Typen (Schnittstellen oder abstrakte Klassen) in Betontypen. Ihr Beispiel hat keine abstrakten Typen, so dass es nicht wirklich viel Sinn macht.

Mark Seeman hat es richtig gemacht. Und ich sympathisiere mit deiner Verwirrung. Ich ging es selbst durch, als ich lernte, automatische Abhängigkeitsinjektionsbehälter zu verwenden. Das Problem ist, dass es viele gültige und vernünftige Möglichkeiten gibt, Objekte zu entwerfen und zu verwenden. Dennoch arbeiten nur einige dieser Ansätze mit automatischen Abhängigkeitsinjektionsbehältern.

Meine persönliche Geschichte: Ich habe OO -Prinzipien der Objektkonstruktion und der Inversion der Kontrolle gelernt, lange bevor ich lernte, wie man die Inversion von Kontrollbehältern wie die Einheit oder die Schloss Windsor -Behälter verwendet. Ich habe die Gewohnheit erworben, so diesen zu schreiben:

public class Foo
{
   IService _service;
   int _accountNumber;

   public Foo(IService service, int accountNumber)
   {
      _service = service;
      _accountNumber = accountNumber;
   }
   public void SaveAccount()
   {
       _service.Save(_accountNumber);

   }
}
public class Program
{
     public static void Main()
     {
        Foo foo = new Foo(new Service(),1234);
        foo.Save();
     }
}

In diesem Design ist meine FOO -Klasse dafür verantwortlich, Konten in der Datenbank zu speichern. Es benötigt eine Kontonummer, um dies zu tun, und einen Dienst, um die schmutzige Arbeit zu erledigen. Dies ähnelt etwas den oben angegebenen konkreten Klassen, bei denen jedes Objekt einige eindeutige Werte im Konstruktor einnimmt. Dies funktioniert gut, wenn Sie die Objekte mit Ihrem eigenen Code instanziieren. Sie können die entsprechenden Werte zum richtigen Zeitpunkt übergeben.

Als ich jedoch über automatische Abhängigkeitsinjektionsbehälter erfuhr, stellte ich fest, dass ich Foo nicht mehr von Hand instanziierte. Der Container würde die Konstruktorargumente für mich instanziieren. Dies war eine große Bequemlichkeit für die Dienste wie Iservice. Aber es funktioniert offensichtlich nicht so gut für Ganzzahlen und Saiten und dergleichen. In diesen Fällen würde es einen Standardwert darstellen (wie Null für eine Ganzzahl). Stattdessen war ich es gewohnt, kontextspezifische Werte wie Kontonummer, Name usw. zu bestehen, also musste ich meinen Codierungsstil und Design so anpassen, dass es so ist:

public class Foo
{
   IService _service;
   public Foo(IService service)
   {
      _service = service;
   }
   public void SaveAccount(int accountNumber)
   {
       _service.Save(accountNumber);

   }
}
public class Program
{
     public static void Main()
     {
        Foo foo = new Foo(new Service());
        foo.Save(1234);
     }
}

Es scheint, dass beide Foo -Klassen gültige Designs sind. Die zweite ist jedoch mit automatischer Abhängigkeitsinjektion und die erste nicht.

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