2012-07-26 7 views
8

Ich verwende Autofac als Ioc Container. Ich habe drei Klassen:So registrieren Sie diese Klasse In Autofac

class Service 
{ 
    public Service(Repository rep,UnitOfWork context){} 

} 

Class Repository 
{ 
    public Repository(UnitOfWork context){} 
} 

class UnitOfWork{} 

die Service- und Repository benötigen die gleiche Instanz von UnitOfWork

Wie das zu tun? und wie es wirte in XmlConfiguration

+0

I Entschuldigung, mein Englisch ist schlecht – DotDot

Antwort

30

EDIT: ich falsch verstanden dies und dachte, es eine Frage war, wie Autofac zu verwenden, um Abhängigkeiten zu registrieren. Wenn Sie dasselbe UnitOfWork beibehalten möchten, müssen Sie die Lebensdauer der Instanz auf etwas beschränken. Wenn Sie dies in einer ASP.NET oder WCF-Anwendung verwenden können Sie Ihre Abhängigkeiten wie folgt registrieren:

typeBuilder.RegisterType<UnitOfWork>().InstancePerLifetimeScope(); 
typeBuilder.RegisterType<Repository>(); 
typeBuilder.RegisterType<Service>(); 

Das erste, was Sie tun müssen, um einen Behälter zu verwenden, wie Autofac registrieren ist Ihre Abhängigkeiten. In Autofac können Sie das ein paar Möglichkeiten, aber alle von ihnen verlassen sich auf die Verwendung der a ContainerBuilder. Die ContainerBuilder stützt sich auf Erweiterungsmethoden, so stellen Sie sicher, dass Sie eine using-Anweisung für den Autofac-Namespace haben.

Sie können die Fabrikmethoden explizit definieren:

// Explicitly 
var builder = new ContainerBuilder(); 
builder.Register<UnitOfWork>(b => new UnitOfWork()); 
builder.Register<Repository>(b => new Repository(b.Resolve<UnitOfWork>())); 
builder.Register(b => new Service(b.Resolve<Repository>(), b.Resolve<UnitOfWork>())); 

Mit ContainerBuilder wir Zugriff auf die Register<>() Methode, um die Service-Schnittstelle zur Verfügung zu stellen (das ist, wie wir die Container für den Service fragen) in diesem Fall Ich benutze keine Interfaces, nur den eigentlichen Typ. Jedes Mal, wenn Sie den Container nach einem UnitOfWork fragen, wird die Factory-Methode new UnitOfWork() verwendet, um eine zu generieren. Im wirklichen Leben würden Sie wahrscheinlich nach einem IUnitOfWork fragen. Dies kann alles ein wenig ausführlich sein, aber es ist sehr praktisch, wenn Sie benutzerdefinierte Logik für die Erstellung von Abhängigkeiten benötigen.

Sie können den Builder wie jeden anderen Abhängigkeitscontainer verwenden und nur die Typen registrieren.

// Implicitly 
var typeBuilder = new ContainerBuilder(); 
typeBuilder.RegisterType<UnitOfWork>(); 
typeBuilder.RegisterType<Repository>(); 
typeBuilder.RegisterType<Service>(); 

Dieser Ansatz beruht alle Abhängigkeiten auf die Registrierung einer Klasse aufzubauen benötigt. Der Container verwendet dann die Reflektion, um alle Konstruktorargumente aufzulösen. Wenn ein Argument nicht registriert ist, löst der Container eine Ausnahme mit dem Typ aus, der nicht aufgelöst werden konnte. In diesem Fall hat der Dienst eine Abhängigkeit von UnitOfWork und Repository. Repository hat auch eine Abhängigkeit von UnitOfWork. Diese Abhängigkeiten werden als Konstruktorargumente ausgedrückt. Um einen Repository oder einen Service aus dem Container anzufordern, müssen alle Abhängigkeiten registriert sein.

Sie können den Konfigurationsansatz verwenden.

Wenn Sie eine Datei app.config verwenden, können Sie Ihre Konfigurationsdatei wie folgt definieren:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
    <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/> 
    </configSections> 

    <autofac defaultAssembly="AutoFacTest"> 
    <components> 
     <component 
       type="AutoFacTest.Repository, AutoFacTest" 
       service="AutoFacTest.Repository" /> 

     <component 
       type="AutoFacTest.UnitOfWork, AutoFacTest" 
       service="AutoFacTest.UnitOfWork" /> 

     <component 
       type="AutoFacTest.Service, AutoFacTest" 
       service="AutoFacTest.Service" /> 
    </components> 
    </autofac> 
</configuration> 

Zunächst Hinweis, dass wir eine Config-Abschnitt definieren (man beachte die <ConfigSections>). Dann können wir einen <autofac> Abschnitt erstellen, der alle unsere Abhängigkeiten definiert. Die Notation ist ziemlich einfach, Sie erstellen grundsätzlich eine <component> für jede Abhängigkeit.Jede Komponente hat ein service Attribut, das den Typ definiert, der angefordert wird. Es gibt auch ein type Attribut, das das Objekt definiert, das erstellt werden soll, wenn eine Instanz des Dienstes angefordert wird. Dies ist analog zu builder.Register<UnitOfWork>(b => new UnitOfWork()) wobei UnitOfWork der angeforderte Dienst (und in diesem Fall) auch der zu erstellende Typ ist.

Um den Generator mit der Konfiguration zu erstellen, verwenden Sie ein ConfigurationSettingsReader()

// Config 
var configBuilder = new ContainerBuilder(); 
configBuilder.RegisterModule(new ConfigurationSettingsReader("autofac")); 

Sie haben im Namen des Konfigurationsabschnittes passieren (in diesem Fall autofac). Sobald Sie die Abhängigkeiten konfiguriert haben, müssen Sie einen Container erstellen. Die ContainerBuilder enthält eine Methode, dies zu tun:

var container = builder.Build(); 
var typeContainer = typeBuilder.Build(); 
var configContainer = configBuilder.Build(); 

Und sobald Sie die Container haben, können Sie Instanzen Ihres Service anfordern:

container.Resolve<Service>().DoAwesomeness(); 
typeContainer.Resolve<Service>().DoAwesomeness(); 
configContainer.Resolve<Service>().DoAwesomeness(); 

Gesamtprogramm:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Autofac; 
using Autofac.Configuration; 

namespace AutoFacTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Explicitly 
      var builder = new ContainerBuilder(); 
      builder.Register<UnitOfWork>(b => new UnitOfWork()); 
      builder.Register<Repository>(b => new Repository(b.Resolve<UnitOfWork>())); 

      builder.Register(b => new Service(b.Resolve<Repository>(), b.Resolve<UnitOfWork>())); 

      // Implicitly 
      var typeBuilder = new ContainerBuilder(); 
      typeBuilder.RegisterType<UnitOfWork>(); 
      typeBuilder.RegisterType<Repository>(); 
      typeBuilder.RegisterType<Service>(); 

      // Config 
      var configBuilder = new ContainerBuilder(); 
      configBuilder.RegisterModule(new ConfigurationSettingsReader("autofac")); 

      var container = builder.Build(); 
      var typeContainer = typeBuilder.Build(); 
      var configContainer = configBuilder.Build(); 


      container.Resolve<Service>().DoAwesomeness(); 
      typeContainer.Resolve<Service>().DoAwesomeness(); 
      configContainer.Resolve<Service>().DoAwesomeness(); 
      Console.Read(); 
     } 
    } 

    public class Repository 
    { 
     private readonly UnitOfWork _unitOfWork; 
     public Repository(UnitOfWork uow) 
     { 
      _unitOfWork = uow; 
     } 

     public void PrintStuff(string text) 
     { 
      Console.WriteLine(text); 
     } 
    } 

    public class Service 
    { 
     private readonly Repository _repository; 
     private readonly UnitOfWork _unitOfWork; 

     public Service(Repository repo, UnitOfWork uow) 
     { 
      _repository = repo; 
      _unitOfWork = uow; 
     } 
     public void DoAwesomeness() 
     { 
      _repository.PrintStuff("Did awesome stuff!"); 
      _unitOfWork.Commit(); 
     } 
    } 

    public class UnitOfWork 
    { 
     public bool Commit() 
     { 
      return true; 
     } 
    } 


} 
+0

Ich habe '' '' ConfigurationSettingsReader''' Konstruktor, woher kommt das? – HoKy22

+0

http://stackoverflow.com/questions/39364698/autofac-upgrade-to-version-4-0-0-is-missing-configurationsettingsreader Wie geht es für Autofac 4.2? – HoKy22