2011-10-15 23 views
5

Necesito cambiar la propiedad Capacity de la variable dinámica del tipo List<*DynamicType*>. El problema es que Activator rendimientos variables object -casted si el tipo de variable no se especifica en lugar de List<*DynamicType*> adecuado y lo mejor que puedo hacer es echarlo a los IList:Casting a una lista genérica de variables de tipo dinámico

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

Después de buscar encontré un solo truco:

dynamic dynamicList = list; 
dynamicList.Capacity = dataRowsCount; 

Aunque esto sería aceptable en mi caso, me pregunto si hay otra forma de hacerlo.

Respuesta

3

Tal vez esto es más simple:

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

Cuál debe utilizar el constructor correcto?

Los genéricos y la reflexión son realmente un dolor en combinación. El truco dynamic aquí no es más feo que establecerlo mediante reflexión (una cadena mágica como literal, frente a un miembro de propiedad no verificado), y dynamic está optimizado internamente y en caché (por tipo), así que no tendría un problema con él . Si tiene que hacer algo más que una propiedad, también puede utilizar dynamic dar la vuelta en un método genérico, para minimizar el feo:

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

que invocará el método genérico con el correcto T. No vale la pena solo para 1 miembro, pero podría ser útil para escenarios más complejos.

+0

Olvidé ese constructor. Como necesito establecer solo esa propiedad, hacerlo de esta manera es realmente más simple. Y también me gusta su sugerencia de usar un método genérico para "lanzar" el objeto IList, muy agradable. –

+0

Por cierto, aunque puedo estar haciendo algo mal, pero asignar el resultado de la variable 'Activator.CreateInstance()' a 'generic' en mi caso no funcionará, porque' list.Add (* Creado dinámicamente dataType object *) ' da como resultado una excepción, y con la 'lista' de prefacturación a' IList' funciona. –

+0

@Dmitry seguro, luego lanzar a 'IList'. No hice eso en el ejemplo, simplemente porque estaba ilustrando el mínimo para realizar las operaciones * en el ejemplo *, y el ejemplo no tiene 'Agregar (...)' –

4

usted puede hacerlo con la reflexión:

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

Una alternativa es escribir un método genérico que hace todo lo que quiere en una forma de tipos estáticos, y llaman con la reflexión de que en su lugar. Esa puede ser una forma práctica de asegurarse de que solo necesita una reflexión.

+0

Bien, no he pensado en la reflexión por alguna razón. Tendré esto en cuenta cuando vuelva a tratar con \ genéricos dinámicos. –

Cuestiones relacionadas