摘:http://www.tracefact.net/CLR-and-Framework/Reflection-Part2.aspx
反射概述 和Type類
1.反射的作用
簡單來說,反射提供這樣幾個能力:1、查看和遍歷類型(及其成員)的基本信息和程序集元數據(metadata);2、遲綁定(Late-Binding)方法和屬性。3、動態創建類型實例(並可以動態調用所創建的實例的方法、字段、屬性)。序章中,我們所採用的那個例子,只是反射的一個用途:查看類型成員信息。接下來的幾個章節,我們將依次介紹反射所提供的其他能力。
2.獲取Type對象實例
反射的核心是Type類,這個類封裝了關於對象的信息,也是進行反射的入口。當你獲得了關於類型的Type對象後,就可以根據Type提供的屬性和方法獲取這個類型的一切信息(方法、字段、屬性、事件、參數、構造函數等)。我們開始的第一步,就是獲取關於類型的Type實例。獲取Type對象有兩種形式,一種是獲取當前加載程序集中的類型(Runtime),一種是獲取沒有加載的程序集的類型。
我們先考慮Runtime時的Type,一般來說有三種獲取方法:
2.1使用Type類提供的靜態方法GetType()
比如我們想要獲得Stream類型的Type實例,則可以這樣:
Type t = Type.GetType("System.IO.Stream");
txtOutput.Text = t.ToString();
注意到GetType方法接受字符串形式的類型名稱。
2.2 使用 typeof 操作符
也可以使用C# 提供的typeof 操作符來完成這一過程:
// 如果在頁首寫入了using System.IO; 也可以直接用 typeof(Stream);
Type t = typeof(System.IO.Stream);
這時的使用有點像泛型,Stream就好像一個類型參數一樣,傳遞到typeof操作符中。
2.3 通過類型實例獲得Type對象
我們還可以通過類型的實例來獲得:
String name = "Jimmy Zhang";
Type t = name.GetType();
使用這種方法時應當注意,儘管我們是通過變量(實例)去獲取Type對象,但是Type對象不包含關於這個特定對象的信息,仍是保存對象的類型(String)的信息。
3.Type類型 及 Reflection命名空間的組織結構
到現在爲止,我已經多次提過Type封裝了類型的信息,那麼這些類型信息都包含什麼內容呢?假設我們現在有一個類型的實例,它的名字叫做 demo,我們對它的信息一無所知,並通過下面代碼獲取了對於它的Type實例:
// 前面某處的代碼實例化了demo對象
Type t = demo.GetType();
現在,我們期望 t 包含了關於 demo 的哪些信息呢?
3.1 demo的類型的基本信息
- 我們當然首先想知道 demo 是什麼類型的,也就是 demo 的類型名稱。
- 我們還想知道該類型位於什麼命名空間下。
- 它的基類型是什麼,以及它在.Net運行庫中的映射類型。
- 它是值類型還是引用類型。
- 它是不是Public的。
- 它是枚舉、是類、是數組、還是接口。
- 它是不是基礎類型(int等)。
- 等等 ...
Type 提供了下面的屬性,用於獲取類型的基本信息,常用的有下面一些:
屬 性 | 說 明 |
Name | 獲取類型名稱 |
FullName | 類型全名 |
Namespace | 命名空間名稱 |
BaseType | 獲取對於基類的Type類型的引用 |
UnderlyingSystemType | 在.Net中映射的類型的引用 |
Attributes | 獲取TypeAttributes位標記 |
IsValueType | 是否值類型 |
IsByRef | 是否由引用傳遞 |
IsEnum | 是否枚舉 |
IsClass | 是否類 |
IsInterface | 是否接口 |
IsSealed | 是否密封類 |
IsPrimitive | 是否基類型(比如int) |
IsAbstract | 是否抽象 |
IsPublic | 是否公開 |
IsNotPublic | 是否非公開 |
IsVisible | 是否程序集可見 |
等等... |
3.2 demon的類型的成員信息
- 我們可能還想知道它有哪些字段。
- 有些什麼屬性,以及關於這些屬性的信息。
- 有哪些構造函數。
- 有哪些方法,方法有哪些參數,有什麼樣的返回值。
- 包含哪些事件。
- 實現了哪些接口。
- 我們還可以不加區分地獲得它的所有 以上成員。
觀察上面的列表,就拿第一條來說,我們想獲取類型都有哪些字段,以及這些字段的信息。而字段都包含哪些信息呢?可能有字段的類型、字段的名稱、字段是否public、字段是否爲const、字段是否是read only 等等,那麼是不是應該將字段的這些信息也封裝起來呢?
實際上,.Net中提供了 FiledInfo 類型,它封裝了關於字段的相關信息。對照上面的列表,類似的還有 PropertyInfo類型、ConstructorInfo類型、MethodInfo類型、EventInfo類型。而對於方法而言,對於它的參數,也會有in參數,out參數,參數類型等信息,類似的,在 System.Reflection 命名空間下,除了有上面的提到的那麼多Info後綴結尾的類型,還有個ParameterInfo 類型,用於封裝方法的參數信息。
最後,應該注意到 Type 類型,以及所有的Info類型均 繼承自 MemberInfo 類型,MemberInfo類型提供了獲取類型基礎信息的能力。
在VS2005中鍵入Type,選中它,再按下F12跳轉到Type類型的定義,縱覽Type類型的成員,發現可以大致將屬性和方法分成這樣幾組:
- IsXXXX,比如 IsAbstract,這組bool屬性用於說明類型的某個信息。(前面的表格已經列舉了一些。)
- GetXXXX(),比如GetField(),返回FieldInfo,這組方法用於獲取某個成員的信息。
- GetXXXXs(),比如GetFields(),返回FieldInfo[],這組方法用戶獲取某些成員信息。
- 還有其他的一些屬性和方法,等後面遇到了再說。
由於MemberInfo是一個基類,當我們獲得一個MemberInfo後,我們並不知道它是PropertyInfo(封裝了屬性信息的對象)還是FieldInfo(封裝了屬性信息的對象),所以,有必要提供一個辦法可以讓我們加以判斷,在Reflection 命名空間中,會遇到很多的位標記,這裏先介紹第一個位標記(本文管用[Flags]特性標記的枚舉稱爲 位標記),MemberTypes,它用於標記成員類型,可能的取值如下:
[Flags]
public enum MemberTypes {
Constructor = 1, // 該成員是一個構造函數
Event = 2, // 該成員是一個事件
Field = 4, // 該成員是一個字段
Method = 8, // 該成員是一個方法
Property = 16, // 該成員是一個屬性
TypeInfo = 32, // 該成員是一種類型
Custom = 64, // 自定義成員類型
NestedType = 128, // 該成員是一個嵌套類型
All = 191, // 指定所有成員類型。
}
反射程序集
在.Net中,程序集是進行部署、版本控制的基本單位,它包含了相關的模塊和類型,我並不打算詳細地去說明程序集及其構成,只是講述如何通過反射獲取程序集信息。
在System.Reflection命名空間下有一個Assembly類型,它代表了一個程序集,幷包含了關於程序集的信息。
在程序中加載程序集時,一般有這麼幾個方法,我們可以使用 Assembly類型提供的靜態方法LoadFrom() 和 Load(),比如:
Assembly asm = Assembly.LoadFrom("Demo.dll");
或者
Assembly asm = Assembly.Load("Demo");
當使用LoadFrom()方法的時候,提供的是程序集的文件名,當將一個程序集添加到項目引用中以後,可以直接寫“文件名.dll”。如果想加載一個不屬於當前項目的程序集,則需要給出全路徑,比如:
Assembly asm = Assembly.LoadFrom(@"C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/System.Web.dll");
使用Load()方法的時候,只用提供程序集名稱即可,不需要提供程序集的後綴名。如果想獲得當前程序集,可以使用Assembly類型的靜態方法 GetExecutingAssembly,它返回包含當前執行的代碼的程序集(也就是當前程序集)。
Assembly as = Assembly.GetExecutingAssembly();
在獲得一個Type類型實例以後,我們還可以使用該實例的Assembly屬性來獲得其所在的程序集:
Type t = typeof(int)
Assembly asm = t.Assembly;
一個程序集可能有多個模塊(Module)組成,每個模塊又可能包含很多的類型,但.Net的默認編譯模式一個程序集只會包含一個模塊,我們現在看下 反射 提供了什麼樣的能力讓我們獲取關於程序集的信息(只列出了部分常用的):
屬 性/方 法 | 說 明 |
FullName | 程序集名稱 |
Location | 程序集的路徑 |
GetTypes() | 獲取程序集包含的全部類型 |
GetType() | 獲取某個類型 |
GetModules() | 獲取程序集包含的模塊 |
GetModule() | 獲取某個模塊 |
GetCustomAttributes() | 獲取自定義特性信息 |
NOTE:程序集和命名空間不存在必然聯繫,一個程序集可以包含多個命名空間,同一個命名空間也可以分放在幾個程序集。
爲了方便進行我們後面的測試,我們現在建立一個Windows控制檯應用程序,我給它起名叫SimpleExplore;然後再添加一個Demo類庫項目,我們將來編寫的代碼就用戶查看這個Demo項目集的類型信息 或者 是對這個程序集中的類型進行遲綁定。這個Demon項目只包含一個命名空間Demo,爲了體現儘可能多的類型同時又Keep Simple,其代碼如下:
namespace Demo {
public abstract class BaseClass {
}
public struct DemoStruct { }
public delegate void DemoDelegate(Object sender, EventArgs e);
public enum DemoEnum {
terrible, bad, common=4, good, wonderful=8
}
public interface IDemoInterface {
void SayGreeting(string name);
}
public interface IDemoInterface2 {}
public sealed class DemoClass:BaseClass, IDemoInterface,IDemoInterface2 {
private string name;
public string city;
public readonly string title;
public const string text = "Const Field";
public event DemoDelegate myEvent;
public string Name {
private get { return name; }
set { name = value; }
}
public DemoClass() {
title = "Readonly Field";
}
public class NestedClass { }
public void SayGreeting(string name) {
Console.WriteLine("Morning :" + name);
}
}
}
現在我們在 SimpleExplore項目中寫一個方法AssemblyExplor(),查看我們Demo項目生成的程序集Demo.dll定義的全部類型:
public static void AssemblyExplore() {
StringBuilder sb = new StringBuilder();
Assembly asm = Assembly.Load("Demo");
sb.Append("FullName(全名):" + asm.FullName + "/n");
sb.Append("Location(路徑):" + asm.Location + "/n");
Type[] types = asm.GetTypes();
foreach (Type t in types) {
sb.Append(" 類型:" + t + "/n");
}
Console.WriteLine(sb.ToString());
}
然後,我們在Main()方法中調用一下,應該可以看到這樣的輸出結果:
FullName(全名):Demo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Location(路徑):E:/MyApp/TypeExplorer/SimpleExplorer/bin/Debug/Demo.dll
模塊: Demo.dll
類型:Demo.BaseClass
類型:Demo.DemoStruct
類型:Demo.DemoDelegate
類型:Demo.DemoEnum
類型:Demo.IDemoInterface
類型:Demo.IDemoInterface2
類型:Demo.DemoClass
類型:Demo.DemoClass+NestedClass
反射基本類型
這裏說反射基本類型,基本類型是針對 泛型類型 來說的,因爲 反射泛型 會更加複雜一些。在前面的範例中,我們獲得了程序集中的所有類型,並循環打印了它們,打印結果僅僅顯示出了類型的全名,而我們通常需要關於類型更詳細的信息,本節我們就來看看如何進一步查看類型信息。
NOTE:因爲一個程序集包含很多類型,一個類型包含很多成員(方法、屬性等),一個成員又包含很多其他的信息,所以如果我們從程序集層次開始寫代碼去獲取每個層級的信息,那麼會嵌套很多的foreach語句,爲了閱讀方便,我會去掉最外層的循環。
1.獲取基本信息
有了前面Type一節的介紹,我想完成這裏應該只是打打字而已,所以我直接寫出代碼,如有必要,會在註釋中加以說明。我們再寫一個方法TypeExplore,用於獲取類型的詳細信息(記得AssemblyExplore只獲取了類型的名稱):
public static void TypeExplore(Type t) {
StringBuilder sb = new StringBuilder();
sb.Append("名稱信息:/n");
sb.Append("Name: " + t.Name + "/n");
sb.Append("FullName: " + t.FullName + "/n");
sb.Append("Namespace: " + t.Namespace + "/n");
sb.Append("/n其他信息:/n");
sb.Append("BaseType(基類型): " + t.BaseType + "/n");
sb.Append("UnderlyingSystemType: " + t.UnderlyingSystemType + "/n");
sb.Append("/n類型信息:/n");
sb.Append("Attributes(TypeAttributes位標記): " + t.Attributes + "/n");
sb.Append("IsValueType(值類型): " + t.IsValueType + "/n");
sb.Append("IsEnum(枚舉): " + t.IsEnum + "/n");
sb.Append("IsClass(類): " + t.IsClass + "/n");
sb.Append("IsArray(數組): " + t.IsArray + "/n");
sb.Append("IsInterface(接口): " + t.IsInterface + "/n");
sb.Append("IsPointer(指針): " + t.IsPointer + "/n");
sb.Append("IsSealed(密封): " + t.IsSealed + "/n");
sb.Append("IsPrimitive(基類型): " + t.IsPrimitive + "/n");
sb.Append("IsAbstract(抽象): " + t.IsAbstract + "/n");
sb.Append("IsPublic(公開): " + t.IsPublic + "/n");
sb.Append("IsNotPublic(不公開): " + t.IsNotPublic + "/n");
sb.Append("IsVisible: " + t.IsVisible + "/n");
sb.Append("IsByRef(由引用傳遞): " + t.IsByRef + "/n");
Console.WriteLine(sb.ToString());
}
然後,我們在Main方法中輸入:
Type t = typeof(DemoClass);
TypeExplore(t);
會得到這樣的輸出:
名稱信息:
Name: DemoClass
FullName: Demo.DemoClass
Namespace: Demo
其他信息:
BaseType(基類型): Demo.BaseClass
UnderlyingSystemType: Demo.DemoClass
類型信息:
Attributes(TypeAttributes位標記): AutoLayout, AnsiClass, Class, Public, Sealed,
BeforeFieldInit
IsValueType(值類型): False
IsEnum(枚舉): False
IsClass(類): True
IsArray(數組): False
IsInterface(接口): False
IsPointer(指針): False
IsSealed(密封): True
IsPrimitive(基類型): False
IsAbstract(抽象): False
IsPublic(公開): True
IsNotPublic(不公開): False
IsVisible: True
IsByRef(由引用傳遞): False
值得注意的是Attributes屬性,它返回一個TypeAttributes位標記,這個標記標識了類型的一些元信息,可以看到我們熟悉的Class、Public、Sealed。相應的,IsClass、IsSealed、IsPublic等屬性也返回爲True。
2.成員信息 與 MemberInfo 類型
我們先考慮一下對於一個類型Type,可能會包含什麼類型,常見的有字段、屬性、方法、構造函數、接口、嵌套類型等。MemberInfo 類代表着 Type的成員類型,值得注意的是Type類本身又繼承自MemberInfo類,理解起來並不困難,因爲一個類型經常也是另一類型的成員。Type類提供 GetMembers()、GetMember()、FindMember()等方法用於獲取某個成員類型。
我們再添加一個方法 MemberExplore(),來查看一個類型的所有成員類型。
public static void MemberExplore(Type t) {
StringBuilder sb = new StringBuilder();
MemberInfo[] memberInfo = t.GetMembers();
sb.Append("查看類型 " + t.Name + "的成員信息:/n");
foreach (MemberInfo mi in memberInfo) {
sb.Append("成員:" + mi.ToString().PadRight(40) + " 類型: " + mi.MemberType + "/n");
}
Console.WriteLine(sb.ToString());
}
然後我們在Main方法中調用一下。
MemberExplore(typeof(DemoClass));
產生的輸出如下:
查看類型 DemoClass的成員信息:
--------------------------------------------------
成員:Void add_myEvent(Demo.DemoDelegate) 類型: Method
成員:Void remove_myEvent(Demo.DemoDelegate) 類型: Method
成員:System.String get_Name() 類型: Method
成員:Void set_Name(System.String) 類型: Method
成員:Void SayGreeting(System.String) 類型: Method
成員:System.Type GetType() 類型: Method
成員:System.String ToString() 類型: Method
成員:Boolean Equals(System.Object) 類型: Method
成員:Int32 GetHashCode() 類型: Method
成員:Void .ctor() 類型: Constructor
成員:System.String Name 類型: Property
成員:Demo.DemoDelegate myEvent 類型: Event
成員:System.String text 類型: Field
成員:Demo.DemoClass+NestedClass 類型: NestedType
我們使用了GetMembers()方法獲取了成員信息的一個數組,然後遍歷了數組,打印了成員的名稱和類型。如同我們所知道的:Name屬性在編譯後成爲了get_Name()和set_Name()兩個獨立的方法;myEvent事件的註冊(+=)和取消註冊(-=)分別成爲了add_myEvent()和remove_myEvent方法。同時,我們發現私有(private)字段name 沒有被打印出來,另外,基類System.Object的成員GetType()和Equals()也被打印了出來。
有的時候,我們可能不希望查看基類的成員,也可能希望查看私有的成員,此時可以使用GetMembers()的重載方法,傳入BindingFlags 位標記參數來完成。BindingFlags位標記對如何獲取成員的方式進行控制(也可以控制如何創建對象實例,後面會說明)。對於本例,如果我們想獲取所有的公有、私有、靜態、實例 成員,那麼只需要這樣修改GetMembers()方法就可以了。
MemberInfo[] memberInfo = t.GetMembers(
BindingFlags.Public |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.DeclaredOnly
);
此時的輸出如下:
查看類型 DemoClass的成員信息:
--------------------------------------------------
成員:Void add_myEvent(Demo.DemoDelegate) 類型: Method
成員:Void remove_myEvent(Demo.DemoDelegate) 類型: Method
成員:System.String get_Name() 類型: Method
成員:Void set_Name(System.String) 類型: Method
成員:Void SayGreeting(System.String) 類型: Method
成員:Void .ctor() 類型: Constructor
成員:System.String Name 類型: Property
成員:Demo.DemoDelegate myEvent 類型: Event
成員:System.String name 類型: Field
成員:Demo.DemoDelegate myEvent 類型: Field
成員:System.String text 類型: Field
成員:Demo.DemoClass+NestedClass 類型: NestedType
可以看到,繼承自基類 System.Object 的方法都被過濾掉了,同時,打印出了私有的 name, myEvent 等字段。
現在如果我們想要獲取所有的方法(Method),那麼我們可以使用 Type類的FindMembers()方法:
MemberInfo[] memberInfo = t.FindMembers(
MemberTypes.Method, // 說明查找的成員類型爲 Method
BindingFlags.Public |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.DeclaredOnly,
Type.FilterName,
"*"
);
Type.FilterName 返回一個MemberFilter類型的委託,它說明按照方法名稱進行過濾,最後一個參數“*”,說明返回所有名稱(如果使用“Get*”,則會返回所有以Get開頭的方法)。現在的輸出如下:
查看類型 DemoClass的成員信息:
--------------------------------------------------
成員:Void add_myEvent(Demo.DemoDelegate) 類型: Method
成員:Void remove_myEvent(Demo.DemoDelegate) 類型: Method
成員:System.String get_Name() 類型: Method
成員:Void set_Name(System.String) 類型: Method
成員:Void SayGreeting(System.String) 類型: Method
MemberInfo 類有兩個屬性值得注意,一個是DeclaringType,一個是 ReflectedType,返回的都是Type類型。DeclaredType 返回的是聲明該成員的類型。比如說,回顧我們之前的一段代碼:
MemberInfo[] members = typeof(DemoClass).GetMembers();
它將返回所有的公有成員,包括繼承自基類的Equals()等方法,對於Equals()方法來說,它的 DeclaringType 返回的是相當於 typeof(Object) 的類型實例,因爲它是在 System.Object中被定義的;而它的ReflectedType 返回的則是相當於 typeof(DemoClass) 類型實例,因爲它是通過 DemoClass 的類型實例被獲取的。
3.字段信息 與 FieldInfo類型
如同我們之前所說,MemberInfo 是一個基類,它包含的是類型的各種成員都公有的一組信息。實際上,對於字段、屬性、方法、事件 等類型成員來說,它們包含的信息顯然都是不一樣的,所以,.Net 中提供了 FiledInfo 類型來封裝字段的信息,它繼承自MemberInfo。
如果我們希望獲取一個類型的所有字段,可以使用 GetFileds()方法。我們再次添加一個方法FieldExplore():
public static void FieldExplore(Type t) {
StringBuilder sb = new StringBuilder();
FieldInfo[] fields = t.GetFields();
sb.Append("查看類型 " + t.Name + "的字段信息:/n");
sb.Append(String.Empty.PadLeft(50, '-') + "/n");
foreach (FieldInfo fi in fields) {
sb.Append("名稱:" + fi.Name + "/n");
sb.Append("類型:" + fi.FieldType + "/n");
sb.Append("屬性:" + fi.Attributes + "/n/n");
}
Console.WriteLine(sb.ToString());
}
產生的輸出如下:
查看類型 DemoClass的字段信息:
--------------------------------------------------
名稱:city
類型:System.String
屬性:Public
名稱:title
類型:System.String
屬性:Public, InitOnly
名稱:text
類型:System.String
屬性:Public, Static, Literal, HasDefault
值得一提的是fi.FieldType 屬性,它返回一個FieldAttributes位標記,這個位標記包含了字段的屬性信息。對比我們之前定義的DemoClass類,可以看到,對於title 字段,它的屬性是public, InitOnly;對於Const類型的text字段,它的屬性爲Public,Static,Literal,HasDefault,由此也可以看出,聲明一個const類型的變量,它默認就是靜態static的,同時,由於我們給了它初始值,所以位標記中也包括HasDefault。
針對於FieldType位標記,FiledInfo 類提供了一組返回爲bool類型的屬性,來說明字段的信息,常用的有:IsPublic, IsStatic, IsInitOnly, IsLiteral, IsPrivate 等。
如果我們想要獲取私有字段信息,依然可以使用重載了的GetFields[]方法,傳入BindingFlags參數,和上面的類似,這裏就不重複了。
4.屬性信息 與 PropertyInfo 類型
和字段類似,也可以通過 GetProperty()方法,獲取類型的所有屬性信息。
public static void PropertyExplore(Type t) {
StringBuilder sb = new StringBuilder();
sb.Append("查看類型 " + t.Name + "的屬性信息:/n");
sb.Append(String.Empty.PadLeft(50, '-') + "/n");
PropertyInfo[] properties = t.GetProperties();
foreach (PropertyInfo pi in properties) {
sb.Append("名稱:" + pi.Name + "/n");
sb.Append("類型:" + pi.PropertyType + "/n");
sb.Append("可讀:" + pi.CanRead + "/n");
sb.Append("可寫:" + pi.CanWrite +"/n");
sb.Append("屬性:" + pi.Attributes +"/n");
}
Console.WriteLine(sb.ToString());
}
輸出如下:
查看類型 DemoClass的屬性信息:
--------------------------------------------------
名稱:Name
類型:System.String
可讀:True
可寫:True
屬性:None
從前面的章節可以看到,Name屬性會在編譯後生成Get_Name()和Set_Name()兩個方法,那麼,應該可以利用反射獲取這兩個方法。PropertyInfo類的GetGetMethod()和GetSetMethod()可以完成這個工作,它返回一個MethodInfo對象,封裝了關於方法的信息,我們會在後面看到。
5.方法信息 與 MethodInfo 類型
與前面的類似,我們依然可以編寫代碼來查看類型的方法信息。
public static void MethodExplore(Type t) {
StringBuilder sb = new StringBuilder();
sb.Append("查看類型 " + t.Name + "的方法信息:/n");
sb.Append(String.Empty.PadLeft(50, '-') + "/n");
MethodInfo[] methods = t.GetMethods();
foreach (MethodInfo method in methods) {
sb.Append("名稱:" + method.Name +"/n");
sb.Append("簽名:" + method.ToString() + "/n");
sb.Append("屬性:" + method.Attributes + "/n");
sb.Append("返回值類型:" + method.ReturnType + "/n/n");
}
Console.WriteLine(sb.ToString());
}
與前面類似,MethodInfo 類也有一個Attributes屬性,它返回一個MethodAttribute,MethodAttribute 位標記標明瞭方法的一些屬性,常見的比如Abstract, Static, Virtual,Public, Private 等。
與前面不同的是,Method可以具有參數 和 返回值,MethodInfo 類提供了 GetParameters() 方法獲取 參數對象的數組,方法的參數都封裝在了 ParameterInfo 類型中。查看ParameterInfo類型的方法與前面類似,這裏就不再闡述了。
6. ConstructorInfo類型、EventInfo 類型
從名稱就可以看出來,這兩個類型封裝了類型 的構造函數 和 事件信息,大家都是聰明人,查看這些類型與之前的方法類似,這裏就不再重複了。
7.小結
本文涉及了反射的最基礎的內容,我們可以利用反射來自頂向下地查看程序集、模塊、類型、類型成員的信息。反射更強大、也更有意思的內容:遲綁定方法、動態創建類型以後會再講到。