2011-10-15 14 views
5

Devo modificare la proprietà Capacity della variabile dinamica di tipo List<*DynamicType*>. Il problema è che i rendimenti Activatorobject variabile -casted se il tipo di variabile non è specificato, invece di una corretta List<*DynamicType*> e il meglio che posso fare è di gettarlo ai IList:Trasmissione a un elenco generico di variabili di tipo dinamico

DynamicTypeBuilder builder = new DynamicTypeBuilder() { ... }; 
Type dataType = builder.GenerateType(...); 
Type listDataType = typeof(List<>).MakeGenericType(dataType); 
IList list = (IList)Activator.CreateInstance(listDataType); 

Dopo qualche ricerca ho trovato solo un trucco:

dynamic dynamicList = list; 
dynamicList.Capacity = dataRowsCount; 

Anche se questo sarebbe accettabile nel mio caso mi chiedo se c'è un altro modo per farlo.

risposta

3

Forse questo è più semplice:

object list = Activator.CreateInstance(listDataType, 
    new object[]{dataRowsCount}); 

Che dovrebbe utilizzare il costruttore corretta?

Generics e reflection sono davvero un dolore in combinazione. L'hack dynamic non è più brutto di impostarlo tramite reflection (una stringa magica come letterale, contro un membro della proprietà non verificato), e dynamic è ottimizzato internamente e memorizzato nella cache (per tipo), quindi non avrei alcun problema con esso . Se avete bisogno di fare di più che una proprietà, è anche possibile utilizzare dynamic per capovolgere in un metodo generico, per ridurre al minimo il brutto:

void Evil<T>(List<T> list, int capacity) { 
    list.Capacity = capacity; 
    // do other stuff 
} 
... 
dynamic list = Activator.CreateInstance(listDataType); 
Evil(list, dataRowsCount); 

che richiamerà il metodo generico con la corretta T. Non ne vale la pena solo per 1 membro, ma potrebbe essere utile per scenari più complessi.

+0

Hai dimenticato il costruttore. Dato che ho bisogno di impostare solo quella proprietà, farlo in questo modo è davvero più semplice. E mi piace anche il tuo suggerimento di utilizzare un metodo generico per "trasmettere" l'oggetto IList, molto bello. –

+0

BTW, anche se potrei fare qualcosa di sbagliato, ma assegnare il risultato di 'Activator.CreateInstance()' alla variabile 'generic' nel mio caso non funzionerà, perché' list.Add (* DataType creato dinamicamente oggetto *) ' ha come risultato un'eccezione e con '' list' di pre-casting su 'IList' funziona. –

+0

@Diman sicuro, quindi lanciato su 'IList'. Nell'esempio non l'ho fatto, semplicemente perché stavo illustrando il minimo per eseguire le operazioni * nell'esempio *, e l'esempio non ha 'Aggiungi (...)' –

4

si può fare con la riflessione:

var capacityProperty = listDataType.GetProperty("Capacity"); 
capacityProperty.SetValue(list, dataRowsCount, null); 

Un'alternativa è quella di scrivere un metodo generico che fa tutto quello che volete in un modo a tipizzazione statica, e chiamare che con la riflessione, invece. Questo può essere un modo pratico per assicurarti di aver bisogno solo di un pezzo di riflessione.

+0

Bello, non ho pensato al riflesso per qualche motivo. Avrò questo in mente quando mi occuperò nuovamente di dynamic \ generics. –

Problemi correlati