2010-11-16 12 views
7

Estaba tratando de agregar elementos a IList a través de la reflexión, pero al llamar al método "Agregar" se produjo un error "ref. Objeto no establecido". Mientras realizaba la depuración, supe que GetMethod ("Agregar") devolvía una referencia NULA.Agregar elementos a la lista <T> utilizando la reflexión

Type objTyp = typeof(MyObject); //HardCoded TypeName for demo purpose 
var IListRef = typeof (List<>); 
Type[] IListParam = {objTyp};   
object Result = IListRef.MakeGenericType(IListParam); 

MyObject objTemp = new MyObject(); 
Result.GetType().GetMethod("Add").Invoke(Result, new[] {objTemp }); 

Por favor ayuda.

+0

He trabajado bastante con la reflexión hace un tiempo, y llegué a la conclusión de que no me gusta la sobrecarga de 'GetMethod (cadena)', porque nunca supe si volvería. Intente utilizar 'GetMethod (string, Type [])' o 'GetMethod (string, BindingFlags)'. Puede que no funcione, y podría ser solo paranoico, pero recuerdo haber tenido mucha confusión sobre problemas similares antes. – Alxandr

Respuesta

22

usted está tratando de encontrar un método Add en Type, no en List<MyObject> - y luego usted está tratando de invocar en un Type.

MakeGenericType devuelve un tipo, no una instancia de ese tipo. Si desea crear una instancia, generalmente es el Activator.CreateInstance el camino a seguir. Prueba esto:

Type objTyp = typeof(MyObject); //HardCoded TypeName for demo purpose 
var IListRef = typeof (List<>); 
Type[] IListParam = {objTyp};   
object Result = Activator.CreateInstance(IListRef.MakeGenericType(IListParam)); 

MyObject objTemp = new MyObject(); 
Result.GetType().GetMethod("Add").Invoke(Result, new[] {objTemp }); 

(También sugeriría que se inicia siguiendo las convenciones de nombres de variables, pero eso es un asunto aparte.)

+0

Muchas gracias, ahora está funcionando. Me perdí de llamar al "Activador.CrearInstancia". – AbrahamJP

0

Sólo se han creado un tipo genérico, no se ha creado una instancia del tipo Tienes un tipo de lista, pero no tienes una lista.

El variabled Result contiene un objeto Type, por lo Result.Gettype() devuelve el mismo como typeof(Type). Está intentando encontrar un método Add en la clase Type, no su clase de lista.

se puede no utilizar los medicamentos genéricos en lugar de reflexión, por ejemplo .:

public static List<T> CreateListAndAddEmpty<T>() where T : new() { 
    List<T> list = new List<T>(); 
    list.Add(new T()); 
    return list; 
} 
+0

La solución basada en Generics que había sugerido era apta. La razón por la que no opté por los genéricos fue porque el método PropertyInfo.SetValue no aceptaba referencias genéricas de parámetros; de lo contrario, definitivamente habría elegido la versión de Generics. – AbrahamJP

3
private static void Test() 
    { 
     IList<Guid> list = CreateList<Guid>(); 
     Guid objTemp = Guid.NewGuid(); 
     list.Add(objTemp); 
    } 

    private static List<TItem> CreateList<TItem>() 
    { 
     Type listType = GetGenericListType<TItem>(); 
     List<TItem> list = (List<TItem>)Activator.CreateInstance(listType); 
     return list; 
    } 

    private static Type GetGenericListType<TItem>() 
    { 
     Type objTyp = typeof(TItem); 
     var defaultListType = typeof(List<>); 
     Type[] itemTypes = { objTyp }; 
     Type listType = defaultListType.MakeGenericType(itemTypes); 
     return listType; 
    } 

IList.Add (tema objeto); => puedes usar el método Add en la interfaz IList en lugar de Reflection.

+0

No funciona. 'IList Result = (IList) IListRef.MakeGenericType (IListParam);' throws 'InvalidCastException No se puede convertir el objeto de tipo 'System.RuntimeType' para escribir 'System.Collections.IList'. ' –

+1

Sí, tienes razón Alex, gracias tu advertencia. Me perdí que olvidé crear instancia. Y edito el código, y en este momento, está probado y funciona;))) – Doctor

Cuestiones relacionadas