2011-09-06 12 views
9

Questa domanda è un seguito della mia domanda precedente: Autofac: Hiding multiple contravariant implementations behind one composite.Autofac: risoluzione dei tipi di varianti con argomenti di tipo in e out

Sto cercando di trovare i limiti di ciò che possiamo fare con il supporto di covarianza e contravarianza di Autofac. Ho notato che il protocollo ContravariantRegistrationSource di Autofac supporta solo interfacce generiche con un singolo parametro generico contrassegnato con la parola chiave in. Questo sembra limitare l'utilità di questa funzionalità e mi chiedo se Autofac abbia altri modi per estendere il supporto della covarianza e della contravarianza.

Devo ammettere che non lo sto chiedendo a causa di un vero design di applicazione su cui sto lavorando. Sto deliberatamente cercando di trovare i limiti di Autofac per l'educazione.

Quindi considerare la seguente interfaccia:

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

E la seguente implementazione:

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

E la seguente registation:

var builder = new ContainerBuilder(); 

builder.RegisterSource(new ContravariantRegistrationSource()); 

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

var container = builder.Build(); 

Con questo disegno e la configurazione, mi piacerebbe si aspettano di essere in grado di fare questo:

// 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>>(); 

Oppure mettiamola più astrattamente, con le definizioni date:

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

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

e la seguente iscrizione:

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

mi aspetterei le seguenti chiamate per avere successo:

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

Come possiamo farlo con Autofac?

risposta

4

Penso che questo sia un limite che non è probabile superare in Autofac, ma è interessante da esplorare.

Possiamo risolvere in modo controverso perché dato un argomento di tipo generico possiamo trovare tutti i tipi di base/interfaccia a cui tale argomento sarebbe assegnabile. Cioè, dato string possiamo cercare per le implementazioni per object, IComparable ecc

Andando nella direzione opposta - da un tipo di argomento a tutte le sue sottoclassi - non è così facile. Dato object avremmo bisogno di un modo per cercare tutto il resto.

Può essere possibile utilizzare la conoscenza dei componenti in calcestruzzo registrati nel contenitore, ad es. scansiona tutti i componenti alla ricerca di possibili implementazioni e lavora all'indietro, ma questo non è eccezionale per Autofac perché ci affidiamo a un modello "pull" per creare pigramente componenti in molti casi.

Spero che questo sia uno spunto di riflessione, interessato a vedere cosa ti viene in mente.

1

È corretto osservare che lo ContravariantRegistrationSource riconosce solo i tipi con un parametro generico. Guardando allo the source (attualmente alla linea 166 circa) vedrai questa limitazione proprio lì. Guardando a come è richiesta la fonte di registrazione per fornire possibili candidati, posso capire che il superamento della limitazione richiederà una maggiore complessità nell'implementazione.

Direi che questo non dimostra che hai raggiunto i limiti di Autofac, solo i limiti di questa particolare fonte di registrazione. Lo lascerò come esercizio per il lettore per migliorare l'implementazione di ContravariantRegistrationSource e sono certo che il progetto Autofac è più che felice di accettarlo di nuovo nel nucleo.

+0

Il controllo di uguaglianza con 1 sta contando il numero di parametri controvarianti; un numero arbitrario di altri parametri (non controvarianti) può ancora essere gestito. Saluti! –

Problemi correlati