對泛型進行反射

2021-04-20 05:18:46 字數 3722 閱讀 3295

今天在用反射的時候突然想到,之前從來沒有對泛型物件進行反射,故決定嘗試一下

首先要獲取某個泛型類的type,鍵入如下**:

type t = type.gettype("system.collections.generic.list");

但是除錯發現,t為null,看來類名寫的不對,再試試,

system.collections.generic.list,還是錯,再試試

system.collections.generic.list,還是不對,接連又試了好幾個,還是不對,毛了,先看看list的type究竟是啥,鍵入如下**檢視:

list list = new list();

type t = list.gettype();

console.writeline(t.fullname);

結果輸出:system.collections.generic.list`1[[system.int32, mscorlib, version=2.0.0.0, culture=neutral, publickeytoken=b77a5c561934e089]]

我就暈,咋是這麼個玩意兒?那就再試試

type t = type.gettype("system.collections.generic.list`1[system.int32]");

再次除錯,好,這回對了

接著我們來呼叫一下list的add方法,往裡插入一條資料試試

methodinfo add = t.getmethod("add", new type[1] );//找到add方法

object list = t.invokemember(null,

bindingflags.declaredonly |

bindingflags.public | bindingflags.nonpublic |

bindingflags.instance | bindingflags.createinstance, null, null, new

object );//例項化乙個list物件list

add.invoke(list, new

object );//呼叫add方法,往list中插入一條資料

type t2 = list.gettype();

console.writeline(t2.invokemember("item", bindingflags.getproperty, null, list, new

object ));//獲取list的第一條索引輸出

輸出結果正確,接下來我又想用反射呼叫一下泛型的方法,再寫入以下**:

methodinfo convert = t2.getmethod("convertall", bindingflags.public | bindingflags.instance);//獲取convertall泛型方法

object list2 = type.gettype("system.collections.generic.list`1[system.string]").invokemember(null, bindingflags.declaredonly |

bindingflags.public | bindingflags.nonpublic |

bindingflags.instance | bindingflags.createinstance, null, null, new

object );//例項化乙個list物件list2用以儲存型別轉換後的資料

list2 = convert.invoke(list, new

object );//呼叫convertall方法

console.writeline(list2.gettype().invokemember("item", bindingflags.getproperty, null, list, new

object ));//輸出list2的第乙個索引值

再次除錯,但是很可惜,出現了以下錯誤:不能對 containsgenericparameters 為 true 的型別或方法執行後期繫結操作。

這是怎麼回事?查閱了以下msdn,其中給出的

methodinfo

.containsgenericparameters 屬性的解釋為:

為呼叫泛型方法,方法自身的型別引數或任何封閉型別中必須不含泛型型別定義或開放構造型別。進行這種遞迴確認是很困難的。為方便起見,也為了減少錯誤,containsgenericparameters 屬性提供一種標準方法來區分封閉構造方法(可以呼叫)和開放構造方法(不能呼叫)。如果 containsgenericparameters 屬性返回 true,則方法不能呼叫。

那這樣看來是因為我沒有將泛型的型別先傳進去造成的,再次查閱了一下msdn,發現了makegenericmethod方法,該方法

將當前泛型方法定義的型別引數替換為型別陣列的元素,並返回表示結果構造方法的 methodinfo 物件。行,有戲,再次試試,在invoke前加上如下**:

convert = convert.makegenericmethod(typeof(string));

再次除錯,ok,正常了,至此,我們用對泛型進行反射呼叫成功了,完整**:

type t = type.gettype("system.collections.generic.list`1[system.int32]");

methodinfo add = t.getmethod("add", new type[1] );

object list = t.invokemember(null,

bindingflags.declaredonly |

bindingflags.public | bindingflags.nonpublic |

bindingflags.instance | bindingflags.createinstance, null, null, new

object );

add.invoke(list, new

object );

type t2 = list.gettype();

console.writeline(t2.invokemember("item", bindingflags.getproperty, null, list, new

object ));

methodinfo convert = t2.getmethod("convertall", bindingflags.public | bindingflags.instance);

object list2 = type.gettype("system.collections.generic.list`1[system.string]").invokemember(null, bindingflags.declaredonly |

bindingflags.public | bindingflags.nonpublic |

bindingflags.instance | bindingflags.createinstance, null, null, new

object );

convert = convert.makegenericmethod(typeof(string));

list2 = convert.invoke(list, new

object );

console.writeline(list2.gettype().invokemember("item", bindingflags.getproperty, null, list2, new

object ));

對泛型進行反射

今天在用反射的時候突然想到,之前從來沒有對泛型物件進行反射,故決定嘗試一下 首先要獲取某個泛型類的type,鍵入如下 typet type.gettype system.collections.generic.list 但是除錯發現,t為null,看來類名寫的不對,再試試,system.collec...

泛型反射技巧

1 如何獲得乙個封閉構造型別 closed constructed type 的type物件?假設有如下的型別 class testtype t class testtype t,u 如果要獲得封閉構造型別的type物件,那麼只需要用c 的typeof運算子,或者vb的gettype運算子作用於具體...

泛型和反射

泛型允許程式設計師在 中將變數或引數的型別,先用 型別佔位符 來代替,等到允許的時候再根據傳入的 類 來代替 泛型是指帶型別引數的類,而不是引數本身。類 方法 結構 介面都可定義為泛型 可以定義多個引數 public class person 例項化乙個引用引數型別的泛型,它的記憶體分配的大小是一樣...