2013-03-14 27 views
15

Próbuję zrozumieć wzór fabryki delegatów z Autofac. Wiem jak zaimplementować fabryki przy użyciu iIndex <> z Keyed() rejestracji, który jest wyjaśnione ładnie tu: Configuring an Autofac delegate factory that's defined on an abstract classAutofac delegate factory using func <>

Chciałabym wiedzieć, czy mogę utworzyć fabrykę przy użyciu Func <> i jak chciałbym zrobić rejestracje na poniższym przykładzie:

public enum Service 
{ 
    Foo, 
    Bar 
} 

public interface FooService : IService 
{ 
    ServiceMethod(); 
} 

public interface BarService : IService 
{ 
    ServiceMethod(); 
} 

public class FooBarClient 
{ 
    private readonly IService service; 

    public FooBarClient(Func<Service, IService> service) 
    { 
     this.service = service(Service.Foo); 
    } 

    public void Process() 
    { 
     service.ServiceMethod(); // call the foo service. 
    } 
} 
+0

Dlaczego nie można po prostu użyć 'IIndex <>' z 'Keyed()'? Autofac nie może utworzyć dla ciebie tej 'Func '. Musisz go zarejestrować w swoim kontenerze za pomocą 'Keyed()' lub 'Named()' coś takiego jak: 'builder.Rejestr > (c => s => c.ResolveKeyed (s)); 'Delegowane fabryki mogą tworzyć tylko jeden typ z parametrami i nie wybrać typu opartego na parametrze, ponieważ jest to dla niego" IIndex <> ". – nemesv

+2

Dla IIndex <> będę musiał odwołać się do biblioteki Autofac, której próbuję uniknąć. Chcę, aby mój kod DI był w Composite root (oddzielna biblioteka) tylko jeśli to możliwe. –

Odpowiedz

16

Autofac nie można skonstruować ten Func<Service, IService> dla Ciebie, który pozwala powrócić różnych typów w oparciu o parametr. Właśnie do tego służy IIndex<>.

Jednak jeśli nie chcą/nie mogą korzystać IIndex<> można utworzyć tę funkcję fabryki z pomocą Keyed lub Named i zarejestrować swoją fabrykę w pojemniku:

var builder = new ContainerBuilder(); 
builder.RegisterType<FooBarClient>().AsSelf(); 
builder.RegisterType<FooService>().Keyed<IService>(Service.Foo); 
builder.RegisterType<BarService>().Keyed<IService>(Service.Bar); 

builder.Register<Func<Service, IService>>(c => 
{ 
    var context = c.Resolve<IComponentContext>(); 
    return s => context.ResolveKeyed<IService>(s); 
}); 
+0

dzięki nemesv! działa zgodnie z oczekiwaniami !!! jus jedno pytanie, czy będzie jakaś różnica w wydajności - IIndex vs Func? –

+0

Nie wiem, w jaki sposób IIndex jest zaimplementowany i jaki rodzaj jego optymalizacji lub wydajności ma. Możesz sprawdzić implantację lub wykonać testy wydajności dostosowane do scenariusza, aby porównać te dwa. – nemesv

+2

Po prostu próbowałem tego z wersją powodu, ale daje mi to "ObjectDisposedException" ... "Rozwiązałem" to przez wywołanie 'nowego Foo' wewnątrz delegata (co jest biiiig nogo!) –