2011-09-06 14 views
9

To pytanie jest kontynuacją mojego poprzedniego pytania: Autofac: Hiding multiple contravariant implementations behind one composite.Autofac: Rozwiązywanie typów wariantów z argumentami typu in i out

Próbuję znaleźć granice tego, co możemy zrobić z kowariancją i kontrawariancją Autofaca. Zauważyłem, że Autofac ContravariantRegistrationSource obsługuje tylko ogólne interfejsy z jednym ogólnym parametrem, który jest oznaczony słowem kluczowym in. Wydaje się to ograniczać użyteczność tej funkcji i zastanawiam się, czy Autofac ma inne sposoby na rozszerzenie wsparcia kowariancji i kontrawariancji.

Muszę przyznać, że nie pytam o to ze względu na prawdziwy projekt aplikacji, nad którym pracuję. Celowo staram się znaleźć granice Autofac na rzecz edukacji.

więc rozważyć następujący interfejs:

public interface IConverter<in TIn, out TOut> 
{ 
    TOut Convert(TIn value); 
} 

i następujący realizacji:

public class ObjectToStringConverter : IConverter<object, string> 
{ 
    string IConverter<object, string>.Convert(object value) 
    { 
     return value.ToString(); 
    } 
} 

i następujący Kontakt Rejestracja:

var builder = new ContainerBuilder(); 

builder.RegisterSource(new ContravariantRegistrationSource()); 

builder.RegisterType<ObjectToStringConverter>() 
    .As<IConverter<object, string>>(); 

var container = builder.Build(); 

z tym wzorem i konfiguracji, bym spodziewać się, że będzie to możliwe:

// This call succeeds because IConverter<object, string> is 
// explicitly registered. 
container.Resolve<IConverter<object, string>>(); 

// This call fails, although IConverter<string, object> is 
// assignable from IConverter<object, string>. 
container.Resolve<IConverter<string, object>>(); 

Albo pozwól mi umieścić go bardziej abstrakcyjnie, z podanymi definicjami:

public class A { } 
public class B : A { } 
public class C : B { } 

public class AToCConverter : IConverter<A, C> { ... } 

i następnego rejestracji:

builder.RegisterType<AToCConverter>() 
    .As<IConverter<C, A>>(); 

spodziewałbym następujące połączenia do osiągnięcia sukcesu:

container.Resolve<IConverter<C, A>>(); 
container.Resolve<IConverter<B, B>>(); 
container.Resolve<IConverter<A, C>>(); 

Jak możemy to zrobić w Autofac?

Odpowiedz

4

Uważam, że jest to ograniczenie, którego nie będziemy w stanie pokonać w Autofac, ale warto je zbadać.

Możemy wykonać sprzeczne "rozwiązanie", ponieważ biorąc pod uwagę ogólny typ argumentu, możemy znaleźć wszystkie typy bazowe/interfejsy, do których można przypisać ten argument. Oznacza to, że biorąc pod uwagę string możemy szukać wdrożeń dla object, IComparable itp

Idąc w przeciwnym kierunku - od typu argumentu do wszystkich jej podklas - nie jest tak łatwo. Biorąc pod uwagę object, potrzebowalibyśmy jakiegoś sposobu na poszukiwanie innych rzeczy.

Może być możliwe wykorzystanie wiedzy o składnikach betonowych zarejestrowanych w pojemniku, np. zeskanuj wszystkie komponenty, szukając możliwych implementacji i pracuj wstecz, ale nie jest to dobre dla Autofac, ponieważ polegamy na modelu "pull", aby leniwie tworzyć komponenty w wielu przypadkach.

Mam nadzieję, że to jest jedzenie do przemyśleń, zainteresowane tym, co wymyślisz.

1

Masz rację, obserwując, że ContravariantRegistrationSource rozpoznaje tylko typy z jednym parametrem generycznym. Patrząc na the source (obecnie w przybliżeniu linii 166) zobaczysz to ograniczenie właśnie tam. Patrząc na to, w jaki sposób źródło rejestracji jest wymagane, aby dostarczyć potencjalnych kandydatów, rozumiem, że zniesienie tego ograniczenia będzie wymagać większej złożoności w realizacji.

Powiedziałbym, że to nie dowodzi, że osiągnąłeś limity autofac, tylko limity tego konkretnego źródła rejestracji. Zostawię to jako ćwiczenie dla czytelnika, aby poprawić implementację ContravariantRegistrationSource i jestem pewien, że projekt Autofac z przyjemnością zaakceptuje go z powrotem do rdzenia.

+0

Sprawdzanie równości przez 1 oznacza liczbę parametrów przeciwstawnych; dowolna liczba innych parametrów (nie będących przeciwwariantami) nadal może być obsługiwana. Twoje zdrowie! –