2016-04-24 8 views
5

Ich frage mich, ist es irgendeine Nebenwirkung die Behälter in mirRegister Container selbst Mit Autofac

IContainer container; 
ContainerBuilder builder = new ContainerBuilder(); 
container = builder.Build(); 
builder.RegisterInstance(container).As<IContainer>(); 

zur Registrierung und die Verwendung es wie diese

builder.RegisterType<IManagmentServiceImp>().As<ManagmentServiceImp>() 
    .WithParameter(new ResolvedParameter(
      (pi, ctx) => pi.ParameterType == typeof(IContainer) && pi.Name == "Container", 
      (pi, ctx) => container 
)); 

oder ob sie auch funktionieren.

Antwort

10

Ihr Code ist nicht sicher, weil Sie eine Instanz registrieren, bevor sie initialisiert wurde.

Wenn Sie Zugriff auf den Container innerhalb einer Komponente haben müssen (was keine gute Idee ist), können Sie eine Abhängigkeit von ILifetimeScope haben, die Resolve Methoden haben.

public class ManagmentServiceImp 
{ 
    public ManagmentServiceImp(ILifetimeScope scope) 
    { 
    } 
} 

ILifetimeScope wird automatisch registriert, innerhalb Autofac Sie brauchen keine Registrierung für es hinzuzufügen.

Weitere Informationen finden Sie unter Controlling Scope and Lifetime von Autofac Dokumentation.

Übrigens ist es keine gute Praxis, Abhängigkeiten von Ihrem IoC-Container zu haben. Es sieht so aus, als ob Sie Service Locator Anti-Pattern verwenden. Wenn Sie den Behälter zu faul Lastabhängigkeit benötigen, können Sie Zusammensetzung mit Func<T> oder Lazy<T>

public class ManagmentServiceImp 
{ 
    public ManagmentServiceImp(Lazy<MyService> myService) 
    { 
     this._myService = myService; 
    } 

    private readonly Lazy<MyService> _myService; 
} 

In diesem Fall verwenden können, MyService erstellt werden beim ersten Zugriff auf sie.

Weitere Informationen finden Sie unter Implicit Relationship von der Autofac Dokumentation.

1

Da Sie builder.RegisterInstance() eine Instanz des Containers bereitstellen müssen, müssen Sie sie initialisieren, BEVOR Sie sie als Argument übergeben, was Sie gerade nicht tun. Wenn Sie Ihren Container Builder jedoch so strukturieren, dass er NACH der Registrierung (und Container-Initialisierung) erstellt, können Sie die Container-Instanz in Ihrer Klasse erfolgreich auflösen.

Bitte beachten Sie, dass dies sicherlich ein Design-Geruch in Dependency Injection ist und Sie dies absolut nicht tun sollten. Ihr Container/Kernel sollte nur auf der obersten Ebene Ihres Objektdiagramms existieren. Wenn Sie mit der Injektion Ihres Containers beginnen, sind Sie fast sicher auf dem Weg zum Service Locator Anti-Pattern.

void Main() 
{ 
    IContainer container = new ContainerBuilder().Build(); 
    ContainerBuilder builder = new ContainerBuilder(); 

    builder.RegisterInstance(container).As<IContainer>(); 

    builder.RegisterType<ManagementServiceImp>().As<IManagmentServiceImp>() 
     .WithParameter(new ResolvedParameter(
      (pi, ctx) => pi.ParameterType == typeof(IContainer) && pi.Name == "Container", 
      (pi, ctx) => container 
    )); 

    container = builder.Build(); 
    var instance = container.Resolve<IManagmentServiceImp>(); 
} 

public class ManagementServiceImp : IManagmentServiceImp 
{ 
    private IContainer _container; 

    public ManagementServiceImp(IContainer Container) 
    { 
     _container = Container; 
     _container.Dump(); 
    } 
} 

public interface IManagmentServiceImp { } 
+0

@torvin in welcher Weise wird der Behälter nicht konfiguriert und in welcher Weise dies die Notwendigkeit des OP nicht lösen? –

+0

Entschuldigung, ich habe versehentlich meinen Kommentar entfernt.Es war "Das ist falsch, es wird einen nicht konfigurierten Container registrieren" – torvin

+0

@torvin Sie haben immer noch nicht erklärt, wie dies die Anforderungen des OP nicht erfüllt. –

0

Während ich Ihre Frage nicht beantworte. Wenn Sie versuchen, den Container in einer Serviceklasse oder etwas anderem als einem Äquivalent von IModule zu erhalten, ist dies ein Code-Geruch.

Ihr Servicecode sollte nichts über IOC IMO wissen.

+3

Obwohl ich absolut dasselbe über die Verwendung des Containers in etwas anderem als der Registrierung fühle, gibt es Situationen, die ich mir vorstellen könnte wenig Hässlichkeit. Persönlich denke ich, du solltest diese Art von Feedback nicht geben, ohne eine Alternative für den Fragesteller anzubieten ... – DotBert

1

können Sie diese Erweiterung Methode verwenden:

public static void RegisterSelf(this ContainerBuilder builder) 
{ 
    IContainer container = null; 
    builder.Register(c => container).AsSelf(); 
    builder.RegisterBuildCallback(c => container = c); 
} 

es wie folgt verwendet werden: builder.RegisterSelf();