2009-04-14 7 views
4

Ich habe über Autofac gelesen, dass es schnell ist. Ich habe die Programmierung gesehen und es ist sauber. Aber ich bin mir nicht sicher, wie ich es benutzen soll. Ich habe StructureMap verwendet und es hat eine statische ObjectFactory. Ninject den Kernel, aber in Autofac Google Seiten, die sie empfahlen, etwas zu tun, wie folgen aus:Mit Autofac was wären die Vor- und Nachteile

using(var resolver = builder.Build()){ 
    var whatINeed = resolver.Resolve<INeedThisService>(); 
} 

Es ist eine WinForms-Anwendung, so habe ich einen ungültigen Objektzustand aus der oben tun, so dass ich swiched einen globalen IContainer zu haben, und tat es so

using(var resolver = Program.Container.CreateInnerContainer()) 
{ 
    var whatINeed = resolver.Resolve<INeedThisService>(); 
} 

Ich habe es etwa 3 oder 5 Mal verwendet. Aber ist das effizient? Oder soll ich tun, nur so etwas wie

var whatINeed = Program.Resolve<INeedThisService>() 

und unter der Decke

internal static TServervice Resolver<TService>(){ 
     if(_container == null) _container = builder.Build(); 
     return _container.Resolve<TService>(); 
} 

Weichen würden Sie verwenden, und warum. Gibt es eine Strafe für die Arbeit mit CreateInnerContainer()?

Antwort

8

Ich bin kein AutoFac-Experte, habe aber Erfahrung mit anderen IOC-Containern. Ich dachte, diese Frage würde mir einen Grund geben, AutoFac auszuprobieren.

Designs, die auf Ioc-Containern basieren, sollten versuchen, den gesamten Code vom Zugriff auf den Container zu isolieren, mit Ausnahme des Einstiegspunkts oder der Host-Ebene. Ich habe das folgende Beispiel mithilfe von AutoFac und WinForms erstellt, um zu zeigen, wie ein Formular über den Konstruktor auf einen Service zugreifen kann.

Ich bin nicht ganz sicher, warum Sie dachten, dass Sie den inneren Behälter brauchten. Vielleicht können Sie etwas dazu sagen und ich kann Ihnen eine ausführlichere Antwort geben.

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     var builder = new ContainerBuilder(); 
     builder.Register<TheService>().As<INeedThisService>(); 
     builder.Register(f => new Form1(f.Resolve<INeedThisService>())).As<Form1>(); 

     using (var container = builder.Build()) 
     { 
      Application.Run(container.Resolve<Form1>()); 
     } 

    } 
} 

public interface INeedThisService { } 

public class TheService : INeedThisService 
{ 
    public TheService() { Console.WriteLine("ctor ThisService"); } 
} 

public partial class Form1 : Form 
{ 
    public Form1(INeedThisService service) 
    { 
     Console.WriteLine("ctor Form1"); 
     InitializeComponent(); 
    } 
} 
+0

Ich weiß, wie Verwenden Sie einen IoC, ich wollte etwas, das in den Richtlinien des Rahmens für den Zugriff auf meine Dienste war. Mit StructureMap ist eine klare Lösung, Sie verwenden nur ObjectFactory. Aber mit Autofac ist das nicht so klar, und ich würde es hassen, alle Komponenten neu registrieren zu müssen. –

+0

Könnten Sie erklären, was Sie meinen, indem Sie alle Komponenten "neu registrieren"? Suchen Sie nach einer automatischen Registrierung aller Typen in einer Baugruppe? Ich werde in der Zwischenzeit die ObjectFactory von StructureMap betrachten. –

+0

Re-register bedeutet, dass der Teil, der einen IContainer generiert, erneut ausgeführt wird. Die Frage war, wie man den IContainer behalten kann, wenn man ihn durch eine using (..) Anweisung ausführt. –

3

Wie Mark Lindell darauf hingewiesen hat, müssen Sie in der Regel nicht direkt auf den Container in einer Autofac-Anwendung zugreifen.

Der empfohlene Ansatz besteht darin, einmal darauf zuzugreifen, wie es Mark getan hat, wenn die Anwendung gestartet wird.

Andere Komponenten, die anschließend Objekte erstellen müssen, können einen Konstruktorparameter vom Typ IContext deklarieren, den Autofac automatisch injiziert.

Eine Alternative, die keine Abhängigkeit von der Baugruppe Autofac erfordert, ist generiert Fabriken zu verwenden, wie in beschrieben: http://code.google.com/p/autofac/wiki/DelegateFactories

hoffe, das hilft!

+0

Sorry, immer noch nicht klar auf der allgemeinen Richtlinie. Die GeneratedFactories ist jedoch ein interessanter Ansatz. –

5

1) Aus den Beispielen, die Sie angegeben haben, könnte ich annehmen, dass Sie versuchen, IOC-Container hauptsächlich als Service-Locator zu verwenden. Obwohl fast alle Container dies unterstützen, wäre die Hauptverwendung Dependency Injection. Das bedeutet, dass Sie vermeiden sollten, die Resolve-Methode aufzurufen, und lassen Sie Container alle Abhängigkeiten für Sie injizieren. Die Unterschiede zwischen zweien (Service Locator und Dependency Injection) gehen über dieses Thema hinaus.

2) Wenn Sie es immer noch als Service-Locator verwenden möchten, können Sie einfach Root-Container (Program.Container in Ihrem Fall) verwenden, ohne innere Container zu erstellen.Die Folge wäre:

  • ContainerBuilder erstellen
  • Registrieren Sie Komponenten im Builder
  • Stammcontainer erstellen: builder.Build()
  • Container Zugang root Komponenteninstanzen zu lösen

3) Containerhierarchien können in den Szenarios nützlich sein, in denen Sie Singletonverhalten in verschiedenen Bereichen benötigen:

  • Global \ Session \ Request (Web-Anwendungen)
  • Application \ Plugin (Desktop-Plugin-basierte Anwendungen)

BTW Autofac Menschen ermutigen tagged contexts zu verwenden, solche Probleme zu lösen:

+1

Ja, Sie haben Recht, ich habe versucht, es als Service Locator und DI zu verwenden. Ich war zu der Zeit verwirrt, hauptsächlich wegen der Art, wie ich StructureMap benutzte. –

Verwandte Themen