首先了解C#反射的概念
反射是一個運行庫類型發現的過程
通過反射可以得到一個給定程序集所包含的所有類型的列表
這個列表包括給定類型中定義的方法
字段
屬性和事件
也可以動態的發現一組給定類支持的借口
方法的參數和其他
相關信息如基類
命名空間
數據清單等
C#反射命名空間詳細介紹
System
Reflection命名空間內的各類型
(
) Assembly通過它可以加載
了解和操縱一個程序集
(
) AssemblyName 通過它可以找到大量隱藏在程序集的身份中的信息
如版本信息
區域信息等
(
) EventInfo 事件的信息
(
) FieldInfo 字段的信息
(
) MethodInfo 方法的信息
(
) ParameterInfo 參數的信息
(
) PropertyInfo 屬性的信息
(
) MemberInfo 是抽象基類
為 EventInfo
FieldInfo
MethodInfo
PropertyInfo等類型定義了公共的行為
(
) Module 用來訪問帶有多文件程序集的給定模塊
System
Type類
System
Type支持的成員可以分為這樣幾類
(
) Is*** 用來檢查一個類型的元數據
如IsAbstract
IsClass
IsValueType等等
(
) Get*** 用來從類型得到指定項目
如GetEvent()得到類型的一個指定的事件(EventInfo)
另外
這些方法都有一個單數版本和一個復數版本
如GetEvent()對應有一個復數版本GetEvents()
該方法返回一個相關的EventInfo數組
(
) FindMembers() 根據查詢條件返回一個MemberInfo類型的數組
(
)GetType() 該靜態方法根據一個字符串名稱返回一個Type實例
(
)InvokeMember() 對給定項目進行晚期綁定
得到一個Type類型實例的三種方法
因為Type是一個抽象類
所以不能直接使用new關鍵字創建一個Type對象
(
)使用System
Object
GetType()
Person pe=new Person()
//
定義pe為person類的一個對象
Type t=pe
GetType()
(
)使用System
Type
GetType()靜態方法
參數為類型的完全限定名
Type t=Type
GetType(
Entity
Person
)
該方法被重載
允許指定兩個布爾類型的參數
一個用來控制當前類型不能找到時是否拋出異常
另一個用來指示是否區分字符串大小寫
Type t=Type
GetType(
Entity
Person
false
true)
注意到傳入的字符串並沒有包含類型所在的程序集信息
此時該類型便被認為是定義在當前執行的程序集中的
要得到一個外部私有程序集的類型元數據時
字符串參數必須使用類型完全限定名加上類型所在程序集的友好名字
Type t=Type
GetType(
Entity
Person
Entity
)
//
Entity
即為類型所在程序集的友好名字 嵌套類型
傳入的字符串可以指定一個+標記來表示一個嵌套類型
如希望得到一個嵌套在person類中的枚舉類型City的類型信息
則可以這樣
Type t=Type
GetType(
Entity
person+City
)
(
)使用typeof運算符
Type t=typeof(person)
三種方法的比較
使用第一種方法必須先建立一個實例
而後兩種方法不必先建立實例
但使用typeof運算符仍然需要知道類型的編譯時信息
而使用System
Type
GetType()靜態方法不需要知道類型的編譯時信息
所以是首選方法
一個最簡單的C#反射實例
首先編寫類庫如下
namespace ReflectionTest
{
public class WriteTest
{
//帶參數的公共方法
public void WriteString(string s
int i)
{
Console
WriteLine(
WriteString:
+ s + i
ToString())
}
//帶一個參數的靜態方法
public static void StaticWriteString(string s)
{
Console
WriteLine(
StaticWriteString:
+ s)
}
//不帶參數的靜態方法
public static void NoneParaWriteString()
{
Console
WriteLine(
NoParaWriteString
)
}
}
}
class TestApp
{
public static void Main()
{
Assembly ass;
Type type;
Object obj;
//用來測試靜態方法
Object any = new Object()
//指定類庫文件必須使用絕對路徑
不能使用相對路徑
ass = Assembly
LoadFile(@
D:\Source Code\
C#Sudy\
Reflection\
\ReflectTest
dll
)
//命名空間和類的名字必須一起指定
type = ass
GetType(
ReflectionTest
WriteTest
)
/**//*example
*/
MethodInfo method = type
GetMethod(
WriteString
)
string test =
test
;
int i =
;
Object[] parametors = new Object[]{test
i};
//在例子
種必須實例化反射要反射的類
因為要使用的方法並不是靜態方法
//創建對象實例
obj = ass
CreateInstance(
ReflectionTest
WriteTest
)
//執行帶參數的公共方法
method
Invoke(obj
parametors)
//method
Invoke(any
parametors)
//異常
必須實例化反射要反射的類
因為要使用的方法並不是靜態方法
/**//*example
*/
method = type
GetMethod(
StaticWriteString
)
method
Invoke(null
new string[] {
test
})
//第一個參數忽略
//對於第一個參數是無視的
也就是我們寫什麼都不會被調用
//即使我們隨便new了一個any這樣的Object
當然這種寫法是不推薦的
//但是對應在例子
種我們如果Invoke的時候用了類型不一致的實例來做為參數的話
將會導致一個運行時的錯誤
method
Invoke(obj
new string[] {
test
})
method
Invoke(any
new string[] {
test
})
/**//*example
*/
method = type
GetMethod(
NoneParaWriteString
)
//調用無參數靜態方法的例子
這時候兩個參數我們都不需要指定
用null就可以了
s
method
Invoke(null
null)
}
}
從上面的總結中可以看出
對於外部調用的動態庫應用反射時要用到Assembly
LoadFile()
然後才是獲取類型
執行方法等
當用反射創建當前程序集中對象實例或執行某個類下靜態方法時只需通過Type
GetType(
類的完整名
)
From:http://tw.wingwit.com/Article/program/net/201311/12264.html