2017-11-17 6 views
0

Ich möchte Factory-Muster in Autofac implementieren. Dies ist, wie es in Ninject Geographie:Factory-Muster in Autofac

Bind<ICarFilter>().To<CarFilter >(); 
Bind<IBikeFilter>().To<BikeFilter>(); 
Bind<IFilterFacade>().ToFactory().InSingletonScope(); 

Dies ist ein definitnion von IFilterFacade

public interface IFilterFacade 
    {  
     ICarFilter CreateCarFilter(); 

     IBikeFIlter CreateBikeFilter();   
    } 

Wenn ich eine Instanz von CarFilter Art will, alles, was ich tun muß, ist der folgende:

public class HomeController(IFilterFacade filterFacade) 
{ 
    FilterFacade = filterFacade; 
} 

public IFilterFacade FilterFacade { get;set; } 

public ActionResult Index() 
{ 
    var bikeFilter = FilterFacade.CreateBikeFilter(); 
} 

Jedes Beispiel wie man das in AutoFac macht. Ich habe die AutoFac-Dokumentation überprüft, konnte aber die Antwort oder das Beispiel nicht finden.

+0

Ich bin nicht vertraut mit Ninject (Bit ich mit Autofac bin), können Sie bitte das Verhalten, das Sie mit Ninject erklären hatte? Hat Ninject die IFilterFacade-Schnittstelle für Sie dynamisch implementiert? Oder hast du es selbst implementiert? –

+0

@ felix-b Ja, es wird dynamisch von Ninject implementiert. –

+0

Autofac hat keine solche Funktion, AFAIK. Mit Autofac können Sie IComponentContext im Konstruktor Ihres Controllers empfangen. Sie können dann einzelne Komponenten aus diesem IComponentContext auflösen, z. context.Resolve (). Verglichen mit diesem Ansatz ist es für Sie wichtig, die Fassadenschnittstelle zu verwenden. –

Antwort

0

Autofac hat keine solche Funktion wie die dynamische Implementierung einer benutzerdefinierten Factory-Schnittstelle. Es erlaubt zwar die Bindung an Delegierte, aber es ist nicht dasselbe.

Wenn Sie eine Art Fabrik in Konstruktor erhalten möchten, dann erhalten Sie einzelne Komponenten von dieser Fabrik in relevanten Methoden, es ist definitiv mit Autofac möglich.

Zusammensetzung Wurzel

Hier registrieren ich einzelne Komponenten wie Singletons (dies war das Verhalten mit Ninject, wenn ich es richtig bekommen), aber Sie können jede Lebensdauer Option, die Ihren Anforderungen passt.

ContainerBuilder builder = new ContainerBuilder(); 
builder.RegisterType<BikeFilter>().As<IBikeFilter>().SingleInstance(); 
builder.RegisterType<CarFilter>().As<ICarFilter>().SingleInstance(); 

-Controller

public class HomeController 
{ 
    private readonly IComponentContext _components; 

    public HomeController(IComponentContext components) 
    { 
     _components = components; // instead of factory interface 
    } 

    public ActionResult Index() 
    { 
     var bikeFilter = _components.Resolve<IBikeFilter>(); 
     // ... 
    } 
} 

BTW

denke ich, dass Fabrik-Schnittstelle ein nettes Feature von Ninject ist. Ein weiterer zusätzlicher Vorteil ist die Möglichkeit, durch IntelliSense zu erkunden. In meinem Beispiel, wenn ich FilterFacade und das Punktzeichen eintippe, wird mir eine Liste der unterstützten Filter (CreateCarFilter, CreateBikeFilter, ...) gezeigt. Selbst wenn ich mit der Codebasis des Projekts nicht vertraut bin, kann ich mir einen aussuchen, der am besten passt. Mit Autofac, IComponentContext ermöglicht mir Anfrage jede Komponente, die mir nicht hilft, herauszufinden, welche relevanten Komponenten existieren, oder welche Komponenten ich erwarte, dass zu erwarten ist.

0

Es gibt kein Äquivalent von ToFactory in Autofac, aber Sie können einfach eine generische Fabrik gleichwertig implementieren.

public interface IFilterFactory 
{ 
    TFilter Get() where TFilter : IFilter; 
} 

public class FilterFactory : IFilterFactory 
{ 

    public FilterFactory(ILifetimeScope scope) 
    { 
     this._scope = scope; 
    } 

    private readonly ILifetimeScope _scope; 

    public TFilter Get<TFilter>() 
    { 
     return this._scope.Resolve<TFilter>(); 
    } 
} 

Dann es wie folgt registrieren:

builder.RegisterType<FilterFactory>().As<IFilterFactory>(); 
builder.RegisterType<BikeFilter>().As<IBikeFilter>(); 
builder.RegisterType<CarFilter>().As<ICarFilter>(); 

und verwenden Sie es auf diese Weise

public class HomeController 
{ 
    private readonly IFilterFactory _filters; 

    public HomeController(IFilterFactory filters) 
    { 
     this._filters = filters; 
    } 

    public ActionResult Index() 
    { 
     var bikeFilter = this._filters.Get<IBikeFilter>(); 
     // ... 
    } 
} 

ich benennen Sie die Create Methode Get, weil die Methode eine Instanz in der gesamten Lebensdauer aufblicken Umfang und erstellen Sie einen nur bei Bedarf.

Eine andere mögliche Lösung kann Named and Keyed Service und der eingebaute IIndex Typ sein.

builder.RegisterType<BikeFilter>().Named<IFilter>("Bike"); 
builder.RegisterType<CarFilter>().Named<IFilter>("Car"); 

dann auf dem Controller

public class HomeController 
{ 
    private readonly IIndex<String, IFilter> _filters; 

    public HomeController(IIndex<String, IFilter> filters) 
    { 
     this._filters = filters; 
    } 

    public ActionResult Index() 
    { 
     var bikeFilter = this._filters["Bike"]; 
     // ... 
    } 
}