2010-11-16 3 views
7

J'essayais d'ajouter des éléments à IList par réflexion, mais lors de l'appel de la méthode "Add", une erreur était renvoyée "object ref. Pendant le débogage, j'ai appris que GetMethod ("Add") renvoyait une référence NULL.Ajout d'éléments à la liste <T> en utilisant la réflexion

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 }); 

Aidez-nous s'il vous plaît.

+0

J'ai beaucoup travaillé avec la réflexion il y a quelque temps, et j'en suis arrivé à la conclusion que je n'aimais pas la surcharge de 'GetMethod (string)', parce que je ne savais pas si elle reviendrait. Essayez plutôt d'utiliser 'GetMethod (string, Type [])' ou 'GetMethod (string, BindingFlags)'. Peut-être que ça ne marcherait pas, et ça pourrait être juste que je sois paranoïaque, mais je me souviens avoir eu beaucoup de confusion sur des problèmes similaires auparavant. – Alxandr

Répondre

22

Vous essayez de trouver une méthode Add dans Type, pas List<MyObject> - et vous essayez de l'appeler sur un Type.

MakeGenericType renvoie un type et non une instance de ce type. Si vous voulez créer une instance, Activator.CreateInstance est généralement le chemin à parcourir. Essayez ceci:

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 }); 

(Je suggère également que vous commenciez conventions suivantes pour les noms de variables, mais c'est une autre question.)

+0

Merci beaucoup, maintenant son travail. J'ai manqué d'appeler le "Activator.CreateInstance". – AbrahamJP

0

Vous avez seulement créé un type générique, vous n'avez pas créé une instance du type. Vous avez un type de liste, mais vous n'avez pas de liste.

La variable Result contient un objet Type, alors Result.Gettype() renvoie la même valeur que typeof(Type). Vous essayez de trouver une méthode Add dans la classe Type, pas votre classe de liste.

Pouvez-vous pas utiliser les médicaments génériques au lieu de réflexion, par exemple .:

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

La solution basée sur Generics que vous aviez suggérée était une bonne solution. La raison pour laquelle je n'étais pas allé aux génériques était que, la méthode PropertyInfo.SetValue n'acceptait pas de références de paramètres génériques, sinon j'aurais définitivement opté pour la version 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 (point d'objet); => vous pouvez utiliser la méthode Add dans l'interface IList au lieu de Reflection.

+0

Ne fonctionne pas. 'IList Résultat = (IList) IListRef.MakeGenericType (IListParam);' throws 'InvalidCastException Impossible de convertir l'objet de type 'System.RuntimeType' en type 'System.Collections.IList'. ' –

+1

Oui, vous avez raison Alex, merci de votre avertissement. J'ai raté que j'ai oublié créer une instance. Et je modifie le code, et en ce moment, il est testé et il fonctionne;))) – Doctor

Questions connexes