2010-11-16 45 views
7

我试图通过反射向IList添加项目,但在调用“添加”方法时抛出错误“对象参考未设置”。在调试的时候,我开始知道GetMethod(“Add”)返回一个NULL引用。使用反射将项目添加到列表<T>

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

请大家帮忙。

+0

前段时间我用了很多反射工作,得出的结论是我不喜欢'GetMethod(string)'的重载,因为我从来不知道它是否会返回。尝试使用'GetMethod(string,Type [])'或'GetMethod(string,BindingFlags)'。可能没有成功,也可能只是我偏执狂,但我记得之前对类似问题有很多困惑。 – Alxandr 2010-11-16 12:22:43

回答

22

您正试图在Type中找到Add方法,而不是List<MyObject> - 然后您试图在Type上调用它。

MakeGenericType返回一个类型,而不是该类型的一个实例。如果你想创建一个实例,Activator.CreateInstance通常是要走的路。试试这个:

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

(我也建议你开始下面的变量名约定,但这是另外一个问题。)

+0

非常感谢,现在它的工作。我错过了调用“Activator.CreateInstance”。 – AbrahamJP 2010-11-16 12:27:43

0

您只创建了一个泛型类型,你还没有创建一个实例的类型。你有一个列表类型,但你没有列表。

Result variabled包含一个Type对象,所以Result.Gettype()返回相同typeof(Type)。您正试图在Type类中找到Add方法,而不是您的列表类。

你能不能使用泛型,而不是反射,例如:

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

您提出的基于泛型的解决方案是合适的。我没有去泛型的原因是,PropertyInfo.SetValue方法不接受泛型参数引用,否则我肯定会选择泛型版本。 – AbrahamJP 2010-11-16 12:58:06

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(对象的项目); =>您可以在IList接口中使用Add方法而不是Reflection。

+0

不起作用。 IList Result =(IList)IListRef.MakeGenericType(IListParam);'抛出'InvalidCastException无法强制类型为'System.RuntimeType'的对象输入'System.Collections.IList'。 ' – 2016-08-01 12:32:40

+1

是的,你是对的Alex,谢谢你的警告。我错过了,我忘记了创建实例。我编辑代码,在这个时候,它已经过测试,它正在工作;))) – Doctor 2016-08-12 13:01:24