2010-11-16 44 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