7

Problem:mit Abhängigkeiten Instanz einer Klasse erstellen Autofac mit

die Klasse Angenommen:

public class MyAwesomeClass 
{ 
    private IDependCls _dependCls; 
    public MyAwesomeClass(IDependCls dependCls) 
    { 
     _dependCls = dependCls; 
    } 

} 

Und woanders muss ich eine Instanz dieser Klasse bekommen, etwa so:

public class SomewhereElse 
{ 
    public void AwesomeMethod() 
    { 
     //... 
     // AwesomeStuff 
     //... 

     var GetErDone = new MyAwesomeClass(); // PROBLEM! No constructor with 0 arguements 
    } 
} 

Frage ist, kann ich

Vorgeschlagene Lösung 1:

A) muss ein zusätzlicher Konstruktor erstellt werden, der die Abhängigkeit auflöst? Zum Beispiel:

public MyAwesomeClass() // new constructor 
    { 
     _dependCls = DependencyResolver.Current.GetService<IDependCls>(); 
    } 


public class SomewhereElse 
{ 
    public void AwesomeMethod() 
    { 
     var GetErDone = new MyAwesomeClass(); // IT WORKS!! 
    } 
} 

Lösungsvorschlag 2:

B) verwenden, um die Resolver innerhalb AwesomeMethod direkt vor var GetErDone

public class SomewhereElse 
{ 
    public void AwesomeMethod() 
    { 
     var depCls = _dependCls = DependencyResolver.Current.GetService<IDependCls>(); 
     var GetErDone = new MyAwesomeClass(depCls); // IT WORKS!! 
    } 
} 

Autofac Lösung?

C) Einige andere Autofac-Wege?

Auf der Suche nach Best Practices, sowie eine gute Autofac-Lösung, wenn möglich. Ich denke, der erste Weg ist der schlimmste, da optionale Abhängigkeiten zu viel Unordnung führen können.

Zusammenfassung:

Wie erhalte ich eine new MyAwesomeClass() wenn MyAwesomeClass Abhängigkeiten?

+0

Meinst du wirklich _optional_ wenn du es sagst? Wenn es wirklich optional ist, sollten Sie sich die Property-Injection ansehen. Wenn nicht, und Ihr ctor ist wegen zu vieler Abhängigkeiten überladen, vielleicht macht Ihre Klasse zu viel (siehe auch [diese Antwort] (http://stackoverflow.com/a/2420245/1282778)). –

+0

Ich habe keine Frage zu Konstruktor-Clutter, anstatt eine Instanz einer Klasse zu erstellen, die eine Konstruktorinjektion benötigt. –

+0

Danke, dass Sie die Lösungsantwort nicht gepostet haben. Nicht wie jeder andere Körper hat dieses Problem .../s –

Antwort

7

Werfen Sie einen Blick auf die Composition Root Muster.

Sie haben recht, wenn Sie die Abhängigkeitsauflösung hochziehen, verschiebt sich das Problem nur an einen anderen Ort. Wenn Sie es jedoch in Ihrem Objektdiagramm weiter nach oben bewegen, gelangen Sie zum Einstiegspunkt Ihrer Anwendung. Dort werden Sie Ihr Objektdiagramm zusammenstellen.

Vergleichen Sie das mit der Service Locator anti-pattern (mit DependencyResolver in Client-Klassen in Ihrem Fall) und Sie werden sehen, dass Composition Root eine überlegene Lösung ist.

+0

Danke für die Antwort. +1, weil Sie das Konzept wirklich verstehen, und danke für Ihren Artikel. Also ich denke, das wird unvermeidlich passieren? Ich werde mehr über diesen Ansatz lesen, aber ich denke, dass die tatsächliche Zusammensetzung Wurzel, wie Sie es nennen, sollte die Erklärung der Bindung selbst sein. Andernfalls brechen Sie sowohl die Einzelverantwortlichkeit als auch die Trennung von Bedenkenregel. –

+0

Ja, der Kompositionswurzel ist abstrakt als "Speicherort" definiert, Sie können ihn in mehrere Klassen aufteilen, aber es ist wichtig, dass sie in derselben Assembly enthalten sind. Mark Seemann, der Autor der Artikel, schrieb [ein großartiges Buch] (http://www.amazon.com/Dependency-Injection-NET-Mark-Seemann/dp/1935182501) über DI btw. –

+1

@Mihalis - Haben Sie jemals eine zufriedenstellende Lösung mit dem Composition Root-Muster oder anderweitig erhalten?Ihr Beispielcode ist einfach zu folgen und ich würde gerne den Code für die 3. Lösung sehen - Thans –

0

Wenn Sie beispielsweise automatisch über Autofac lösen möchten, können Sie nur von diesem in Konstruktor Ihrer Klasse

  • Inject wählen
  • Inject in Sach unter Verwendung

    var builder = new ContainerBuilder();

    builder.RegisterType<Foo>().PropertiesAutowired();

  • Verwenden Sie den globalen Zugriff von DependencyResolver.Current.GetService<IFoo>();

+0

Ich benutze Konstruktor-Injektion, aber ich frage nach dem tatsächlichen Prozess der Erstellung einer Instanz dieser Klasse. –

+0

Was meinst du damit, eine Instanz dieser Klasse zu erstellen? Welche Klasse möchten Sie instanziieren? Und was genau willst du machen? Prodide mehr Informationen –

+0

Bitte sehen Sie den zweiten grauen Block. Wenn ich den Code so verwende, bekomme ich ein Problem (natürlich). Dann schlage ich zwei Lösungen vor, die ich nicht mag, und bitte um ein drittes - oder eine Bestätigung, dass eines der beiden, die ich vorschlage, Standard ist. Ich werde die Antwort aktualisieren, um tatsächlich meine Lösungen für Sie zu sehen, um zu sehen –

0

In der Klasse enthält MyAwesomeMethod nehmen MyAwesomeClass als Konstrukteur Abhängigkeit. Autofac kümmert sich um die Instanziierung.

+0

ja aber das Problem nur um eine Klasse höher, das ist der Punkt an dem ich eigentlich bin. Was, wenn ich eine Instanz der Klasse erstellen möchte, die 'MyAwesomeMethod' enthält? –

0

Zunächst einmal abgesehen von der Konstruktorinjektion können Sie auch property injection und method injection verwenden. Jedoch ist die Konstruktorinjektion am üblichsten und die schnellste Methode, also schlage ich vor, dabei zu bleiben.

Die zweite Sache, die Sie tun müssen, ist Ihre MyAwesomeClass im Autofac-Container mit seiner Abhängigkeit zu registrieren, sie haben einige nette examples direkt auf ihrer Homepage.

Und das letzte - Sie sollten keine Instanzen von MyAwesomeClass direkt erstellen - stattdessen Autofac verwenden. Hier ist ein aktualisiertes Beispiel:

public void AwesomeMethod() 
{ 
    //... 
    // AwesomeStuff 
    //... 

    var GetErDone = DependencyResolver.Current.GetService<MyAwesomeClass>(); 
} 
+0

erstellt dies eine neue Instanz oder bereits registrierter Dienst? – theusguy

Verwandte Themen