久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

.Net 中的反射(查看基本類(lèi)型信息)

 googo 2011-07-13
.Net 中的反射(查看基本類(lèi)型信息) - Part.2(轉(zhuǎn)載)
2008年03月22日 星期六 13:39

.Net 中的反射(查看基本類(lèi)型信息) - Part.2

反射概述 和Type類(lèi)

1.反射的作用

簡(jiǎn)單來(lái)說(shuō),,反射提供這樣幾個(gè)能力:1,、查看和遍歷類(lèi)型(及其成員)的基本信息和程序集元數(shù)據(jù)(metadata);2,、遲綁定(Late- Binding)方法和屬性,。3、動(dòng)態(tài)創(chuàng)建類(lèi)型實(shí)例(并可以動(dòng)態(tài)調(diào)用所創(chuàng)建的實(shí)例的方法,、字段,、屬性)。序章中,,我們所采用的那個(gè)例子,,只是反射的一個(gè)用 途:查看類(lèi)型成員信息。接下來(lái)的幾個(gè)章節(jié),,我們將依次介紹反射所提供的其他能力,。

2.獲取Type對(duì)象實(shí)例

反射的核心是Type類(lèi),這個(gè)類(lèi)封裝了關(guān)于對(duì)象的信息,,也是進(jìn)行反射的入口,。當(dāng)你獲得了關(guān)于類(lèi)型的Type對(duì)象后,就可以根據(jù)Type提供的屬性和 方法獲取這個(gè)類(lèi)型的一切信息(方法,、字段,、屬性、事件,、參數(shù),、構(gòu)造函數(shù)等)。我們開(kāi)始的第一步,,就是獲取關(guān)于類(lèi)型的Type實(shí)例,。獲取Type對(duì)象有兩種 形式,一種是獲取當(dāng)前加載程序集中的類(lèi)型(Runtime),,一種是獲取沒(méi)有加載的程序集的類(lèi)型,。

我們先考慮Runtime時(shí)的Type,一般來(lái)說(shuō)有三種獲取方法:

2.1使用Type類(lèi)提供的靜態(tài)方法GetType()

比如我們想要獲得Stream類(lèi)型的Type實(shí)例,,則可以這樣:

Type t = Type.GetType("System.IO.Stream");
txtOutput.Text = t.ToString();

注意到GetType方法接受字符串形式的類(lèi)型名稱(chēng),。

2.2 使用 typeof 操作符

也可以使用C# 提供的typeof 操作符來(lái)完成這一過(guò)程:

// 如果在頁(yè)首寫(xiě)入了using System.IO; 也可以直接用 typeof(Stream);
Type t = typeof(System.IO.Stream);

這時(shí)的使用有點(diǎn)像泛型,Stream就好像一個(gè)類(lèi)型參數(shù)一樣,,傳遞到typeof操作符中,。

2.3 通過(guò)類(lèi)型實(shí)例獲得Type對(duì)象

我們還可以通過(guò)類(lèi)型的實(shí)例來(lái)獲得:

String name = "Jimmy Zhang";
Type t = name.GetType();

使用這種方法時(shí)應(yīng)當(dāng)注意,盡管我們是通過(guò)變量(實(shí)例)去獲取Type對(duì)象,,但是Type對(duì)象不包含關(guān)于這個(gè)特定對(duì)象的信息,,仍是保存對(duì)象的類(lèi)型(String)的信息。

3.Type類(lèi)型 及 Reflection命名空間的組織結(jié)構(gòu)

到現(xiàn)在為止,我已經(jīng)多次提過(guò)Type封裝了類(lèi)型的信息,,那么這些類(lèi)型信息都包含什么內(nèi)容呢,?假設(shè)我們現(xiàn)在有一個(gè)類(lèi)型的實(shí)例,它的名字叫做 demo,,我們對(duì)它的信息一無(wú)所知,,并通過(guò)下面代碼獲取了對(duì)于它的Type實(shí)例:

// 前面某處的代碼實(shí)例化了demo對(duì)象
Type t = demo.GetType();

現(xiàn)在,我們期望 t 包含了關(guān)于 demo 的哪些信息呢,?

3.1 demo的類(lèi)型的基本信息

  • 我們當(dāng)然首先想知道 demo 是什么類(lèi)型的,,也就是 demo 的類(lèi)型名稱(chēng),。
  • 我們還想知道該類(lèi)型位于什么命名空間下,。
  • 它的基類(lèi)型是什么,以及它在.Net運(yùn)行庫(kù)中的映射類(lèi)型,。
  • 它是值類(lèi)型還是引用類(lèi)型,。
  • 它是不是Public的。
  • 它是枚舉,、是類(lèi),、是數(shù)組、還是接口,。
  • 它是不是基礎(chǔ)類(lèi)型(int等),。
  • 等等 ...

Type 提供了下面的屬性,用于獲取類(lèi)型的基本信息,,常用的有下面一些:

屬 性 說(shuō) 明
Name 獲取類(lèi)型名稱(chēng)
FullName 類(lèi)型全名
Namespace 命名空間名稱(chēng)
BaseType 獲取對(duì)于基類(lèi)的Type類(lèi)型的引用
UnderlyingSystemType 在.Net中映射的類(lèi)型的引用
Attributes 獲取TypeAttributes位標(biāo)記
IsValueType 是否值類(lèi)型
IsByRef 是否由引用傳遞
IsEnum 是否枚舉
IsClass 是否類(lèi)
IsInterface 是否接口
IsSealed 是否密封類(lèi)
IsPrimitive 是否基類(lèi)型(比如int)
IsAbstract 是否抽象
IsPublic 是否公開(kāi)
IsNotPublic 是否非公開(kāi)
IsVisible 是否程序集可見(jiàn)
等等...

3.2 demon的類(lèi)型的成員信息  

  • 我們可能還想知道它有哪些字段,。
  • 有些什么屬性,以及關(guān)于這些屬性的信息,。
  • 有哪些構(gòu)造函數(shù),。
  • 有哪些方法,方法有哪些參數(shù),,有什么樣的返回值,。
  • 包含哪些事件。
  • 實(shí)現(xiàn)了哪些接口,。
  • 我們還可以不加區(qū)分地獲得它的所有 以上成員,。

觀察上面的列表,就拿第一條來(lái)說(shuō),,我們想獲取類(lèi)型都有哪些字段,,以及這些字段的信息。而字段都包含哪些信息呢,?可能有字段的類(lèi)型,、字段的名稱(chēng)、字段 是否public、字段是否為const,、字段是否是read only 等等,,那么是不是應(yīng)該將字段的這些信息也封裝起來(lái)呢?

實(shí)際上,,.Net中提供了 FiledInfo 類(lèi)型,,它封裝了關(guān)于字段的相關(guān)信息。對(duì)照上面的列表,,類(lèi)似的還有 PropertyInfo類(lèi)型,、ConstructorInfo類(lèi)型、MethodInfo類(lèi)型,、EventInfo類(lèi)型,。而對(duì)于方法而言,對(duì)于它的參 數(shù),,也會(huì)有in參數(shù),,out參數(shù),參數(shù)類(lèi)型等信息,,類(lèi)似的,,在 System.Reflection 命名空間下,除了有上面的提到的那么多Info后綴結(jié)尾的類(lèi)型,,還有個(gè)ParameterInfo 類(lèi)型,,用于封裝方法的參數(shù)信息。

最后,,應(yīng)該注意到 Type 類(lèi)型,,以及所有的Info類(lèi)型均 繼承自 MemberInfo 類(lèi)型,MemberInfo類(lèi)型提供了獲取類(lèi)型基礎(chǔ)信息的能力,。

在VS2005中鍵入Type,,選中它,再按下F12跳轉(zhuǎn)到Type類(lèi)型的定義,,縱覽Type類(lèi)型的成員,,發(fā)現(xiàn)可以大致將屬性和方法分成這樣幾組:

  • IsXXXX,比如 IsAbstract,,這組bool屬性用于說(shuō)明類(lèi)型的某個(gè)信息,。(前面的表格已經(jīng)列舉了一些。)
  • GetXXXX(),,比如GetField(),,返回FieldInfo,這組方法用于獲取某個(gè)成員的信息,。
  • GetXXXXs(),,比如GetFields(),,返回FieldInfo[],這組方法用戶獲取某些成員信息,。
  • 還有其他的一些屬性和方法,,等后面遇到了再說(shuō)。

由于MemberInfo是一個(gè)基類(lèi),,當(dāng)我們獲得一個(gè)MemberInfo后,,我們并不知道它是PropertyInfo(封裝了屬性信息的對(duì)象) 還是FieldInfo(封裝了屬性信息的對(duì)象),所以,,有必要提供一個(gè)辦法可以讓我們加以判斷,,在Reflection 命名空間中,會(huì)遇到很多的位標(biāo)記,,這里先介紹第一個(gè)位標(biāo)記(本文管用[Flags]特性標(biāo)記的枚舉稱(chēng)為 位標(biāo)記),,MemberTypes,它用于標(biāo)記成員類(lèi)型,,可能的取值如下:

[Flags]
public enum MemberTypes {
    Constructor = 1, // 該成員是一個(gè)構(gòu)造函數(shù)
    Event = 2,        // 該成員是一個(gè)事件
    Field = 4,        // 該成員是一個(gè)字段
    Method = 8,           // 該成員是一個(gè)方法
    Property = 16,    // 該成員是一個(gè)屬性
    TypeInfo = 32,    // 該成員是一種類(lèi)型
    Custom = 64,      // 自定義成員類(lèi)型
    NestedType = 128, // 該成員是一個(gè)嵌套類(lèi)型
    All = 191,        // 指定所有成員類(lèi)型,。
}

反射程序集

在.Net中,,程序集是進(jìn)行部署,、版本控制的基本單位,它包含了相關(guān)的模塊和類(lèi)型,,我并不打算詳細(xì)地去說(shuō)明程序集及其構(gòu)成,,只是講述如何通過(guò)反射獲取程序集信息。

在System.Reflection命名空間下有一個(gè)Assembly類(lèi)型,,它代表了一個(gè)程序集,,并包含了關(guān)于程序集的信息。

在程序中加載程序集時(shí),,一般有這么幾個(gè)方法,,我們可以使用 Assembly類(lèi)型提供的靜態(tài)方法LoadFrom() 和 Load(),比如:

Assembly asm = Assembly.LoadFrom("Demo.dll");

或者

Assembly asm = Assembly.Load("Demo");

當(dāng)使用LoadFrom()方法的時(shí)候,,提供的是程序集的文件名,,當(dāng)將一個(gè)程序集添加到項(xiàng)目引用中以后,可以直接寫(xiě)“文件名.dll”,。如果想加載一個(gè)不屬于當(dāng)前項(xiàng)目的程序集,,則需要給出全路徑,比如:

Assembly asm = Assembly.LoadFrom(@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Web.dll");

使用Load()方法的時(shí)候,,只用提供程序集名稱(chēng)即可,,不需要提供程序集的后綴名。如果想獲得當(dāng)前程序集,,可以使用Assembly類(lèi)型的靜態(tài)方法 GetExecutingAssembly,,它返回包含當(dāng)前執(zhí)行的代碼的程序集(也就是當(dāng)前程序集),。

Assembly as = Assembly.GetExecutingAssembly();

在獲得一個(gè)Type類(lèi)型實(shí)例以后,我們還可以使用該實(shí)例的Assembly屬性來(lái)獲得其所在的程序集:

Type t = typeof(int)
Assembly asm = t.Assembly;

一個(gè)程序集可能有多個(gè)模塊(Module)組成,,每個(gè)模塊又可能包含很多的類(lèi)型,,但.Net的默認(rèn)編譯模式一個(gè)程序集只會(huì)包含一個(gè)模塊,我們現(xiàn)在看下 反射 提供了什么樣的能力讓我們獲取關(guān)于程序集的信息(只列出了部分常用的):

屬 性/方 法 說(shuō) 明
FullName 程序集名稱(chēng)
Location 程序集的路徑
GetTypes() 獲取程序集包含的全部類(lèi)型
GetType() 獲取某個(gè)類(lèi)型
GetModules() 獲取程序集包含的模塊
GetModule() 獲取某個(gè)模塊
GetCustomAttributes() 獲取自定義特性信息

NOTE:程序集和命名空間不存在必然聯(lián)系,,一個(gè)程序集可以包含多個(gè)命名空間,,同一個(gè)命名空間也可以分放在幾個(gè)程序集。

為了方便進(jìn)行我們后面的測(cè)試,,我們現(xiàn)在建立一個(gè)Windows控制臺(tái)應(yīng)用程序,,我給它起名叫SimpleExplore;然后再添加一個(gè)Demo類(lèi) 庫(kù)項(xiàng)目,,我們將來(lái)編寫(xiě)的代碼就用戶查看這個(gè)Demo項(xiàng)目集的類(lèi)型信息 或者 是對(duì)這個(gè)程序集中的類(lèi)型進(jìn)行遲綁定,。這個(gè)Demon項(xiàng)目只包含一個(gè)命名空間Demo,為了體現(xiàn)盡可能多的類(lèi)型同時(shí)又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);
       }
    }

}

現(xiàn)在我們?cè)?SimpleExplore項(xiàng)目中寫(xiě)一個(gè)方法AssemblyExplor(),,查看我們Demo項(xiàng)目生成的程序集Demo.dll定義的全部類(lèi)型:

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("   類(lèi)型:" + t + "\n");
    }

    Console.WriteLine(sb.ToString());
}

然后,我們?cè)贛ain()方法中調(diào)用一下,,應(yīng)該可以看到這樣的輸出結(jié)果:

FullName(全名):Demo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Location(路徑):E:\MyApp\TypeExplorer\SimpleExplorer\bin\Debug\Demo.dll
模塊: Demo.dll
   類(lèi)型:Demo.BaseClass
   類(lèi)型:Demo.DemoStruct
   類(lèi)型:Demo.DemoDelegate
   類(lèi)型:Demo.DemoEnum
   類(lèi)型:Demo.IDemoInterface
   類(lèi)型:Demo.IDemoInterface2
   類(lèi)型:Demo.DemoClass
   類(lèi)型:Demo.DemoClass+NestedClass

反射基本類(lèi)型

這里說(shuō)反射基本類(lèi)型,,基本類(lèi)型是針對(duì) 泛型類(lèi)型 來(lái)說(shuō)的,因?yàn)?反射泛型 會(huì)更加復(fù)雜一些,。在前面的范例中,,我們獲得了程序集中的所有類(lèi)型,并循環(huán)打印了它們,,打印結(jié)果僅僅顯示出了類(lèi)型的全名,,而我們通常需要關(guān)于類(lèi)型更詳細(xì)的信 息,本節(jié)我們就來(lái)看看如何進(jìn)一步查看類(lèi)型信息,。

NOTE:因?yàn)橐粋€(gè)程序集包含很多類(lèi)型,,一個(gè)類(lèi)型包含很多成員(方法、屬性等),,一個(gè)成員又包含很多其他的信息,,所以如果我們從程序集層次開(kāi)始寫(xiě)代碼去獲取每個(gè)層級(jí)的信息,那么會(huì)嵌套很多的foreach語(yǔ)句,,為了閱讀方便,,我會(huì)去掉最外層的循環(huán)。

1.獲取基本信息

有了前面Type一節(jié)的介紹,,我想完成這里應(yīng)該只是打打字而已,,所以我直接寫(xiě)出代碼,如有必要,,會(huì)在注釋中加以說(shuō)明,。我們?cè)賹?xiě)一個(gè)方法TypeExplore,,用于獲取類(lèi)型的詳細(xì)信息(記得AssemblyExplore只獲取了類(lèi)型的名稱(chēng)):

public static void TypeExplore(Type t) {
    StringBuilder sb = new StringBuilder();

    sb.Append("名稱(chēng)信息:\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(基類(lèi)型): " + t.BaseType + "\n");
    sb.Append("UnderlyingSystemType: " + t.UnderlyingSystemType + "\n");

    sb.Append("\n類(lèi)型信息:\n");
    sb.Append("Attributes(TypeAttributes位標(biāo)記): " + t.Attributes + "\n");
    sb.Append("IsValueType(值類(lèi)型): " + t.IsValueType + "\n");
    sb.Append("IsEnum(枚舉): " + t.IsEnum + "\n");
    sb.Append("IsClass(類(lèi)): " + t.IsClass + "\n");
    sb.Append("IsArray(數(shù)組): " + t.IsArray + "\n");
    sb.Append("IsInterface(接口): " + t.IsInterface + "\n");
    sb.Append("IsPointer(指針): " + t.IsPointer + "\n");
    sb.Append("IsSealed(密封): " + t.IsSealed + "\n");
    sb.Append("IsPrimitive(基類(lèi)型): " + t.IsPrimitive + "\n");
    sb.Append("IsAbstract(抽象): " + t.IsAbstract + "\n");
    sb.Append("IsPublic(公開(kāi)): " + t.IsPublic + "\n");
    sb.Append("IsNotPublic(不公開(kāi)): " + t.IsNotPublic + "\n");
    sb.Append("IsVisible: " + t.IsVisible + "\n");
    sb.Append("IsByRef(由引用傳遞): " + t.IsByRef + "\n");

    Console.WriteLine(sb.ToString());
}

然后,我們?cè)贛ain方法中輸入:

Type t = typeof(DemoClass);
TypeExplore(t);

會(huì)得到這樣的輸出:

名稱(chēng)信息:
Name: DemoClass
FullName: Demo.DemoClass
Namespace: Demo

其他信息:
BaseType(基類(lèi)型): Demo.BaseClass
UnderlyingSystemType: Demo.DemoClass

類(lèi)型信息:
Attributes(TypeAttributes位標(biāo)記): AutoLayout, AnsiClass, Class, Public, Sealed,
BeforeFieldInit
IsValueType(值類(lèi)型): False
IsEnum(枚舉): False
IsClass(類(lèi)): True
IsArray(數(shù)組): False
IsInterface(接口): False
IsPointer(指針): False
IsSealed(密封): True
IsPrimitive(基類(lèi)型): False
IsAbstract(抽象): False
IsPublic(公開(kāi)): True
IsNotPublic(不公開(kāi)): False
IsVisible: True
IsByRef(由引用傳遞): False

值得注意的是Attributes屬性,,它返回一個(gè)TypeAttributes位標(biāo)記,,這個(gè)標(biāo)記標(biāo)識(shí)了類(lèi)型的一些元信息,可以看到我們熟悉的Class,、Public,、Sealed。相應(yīng)的,,IsClass,、IsSealed、IsPublic等屬性也返回為T(mén)rue,。

2.成員信息 與 MemberInfo 類(lèi)型

我們先考慮一下對(duì)于一個(gè)類(lèi)型Type,,可能會(huì)包含什么類(lèi)型,常見(jiàn)的有字段,、屬性,、方法、構(gòu)造函數(shù),、接口,、嵌套類(lèi)型等。MemberInfo 類(lèi)代表著 Type的成員類(lèi)型,,值得注意的是Type類(lèi)本身又繼承自MemberInfo類(lèi),,理解起來(lái)并不困難,,因?yàn)橐粋€(gè)類(lèi)型經(jīng)常也是另一類(lèi)型的成員,。Type類(lèi)提 供 GetMembers()、GetMember(),、FindMember()等方法用于獲取某個(gè)成員類(lèi)型,。

我們?cè)偬砑右粋€(gè)方法 MemberExplore(),來(lái)查看一個(gè)類(lèi)型的所有成員類(lèi)型,。

public static void MemberExplore(Type t) {
    StringBuilder sb = new StringBuilder();

    MemberInfo[] memberInfo = t.GetMembers();

    sb.Append("查看類(lèi)型 " + t.Name + "的成員信息:\n");

    foreach (MemberInfo mi in memberInfo) {
       sb.Append("成員:" + mi.ToString().PadRight(40) + " 類(lèi)型: " + mi.MemberType + "\n");
    }

    Console.WriteLine(sb.ToString());
}

然后我們?cè)贛ain方法中調(diào)用一下,。

MemberExplore(typeof(DemoClass));

產(chǎn)生的輸出如下:

查看類(lèi)型 DemoClass的成員信息:
--------------------------------------------------
成員:Void add_myEvent(Demo.DemoDelegate)      類(lèi)型: Method
成員:Void remove_myEvent(Demo.DemoDelegate)   類(lèi)型: Method
成員:System.String get_Name()                 類(lèi)型: Method
成員:Void set_Name(System.String)             類(lèi)型: Method
成員:Void SayGreeting(System.String)          類(lèi)型: Method
成員:System.Type GetType()                    類(lèi)型: Method
成員:System.String ToString()                 類(lèi)型: Method
成員:Boolean Equals(System.Object)             類(lèi)型: Method
成員:Int32 GetHashCode()                      類(lèi)型: Method
成員:Void .ctor()                             類(lèi)型: Constructor
成員:System.String Name                       類(lèi)型: Property
成員:Demo.DemoDelegate myEvent                類(lèi)型: Event
成員:System.String text                       類(lèi)型: Field
成員:Demo.DemoClass+NestedClass               類(lèi)型: NestedType

我們使用了GetMembers()方法獲取了成員信息的一個(gè)數(shù)組,然后遍歷了數(shù)組,,打印了成員的名稱(chēng)和類(lèi)型,。如同我們所知道的:Name屬性在編 譯后成為了get_Name()和set_Name()兩個(gè)獨(dú)立的方法;myEvent事件的注冊(cè)(+=)和取消注冊(cè)(-=)分別成為了 add_myEvent()和remove_myEvent方法,。同時(shí),,我們發(fā)現(xiàn)私有(private)字段name 沒(méi)有被打印出來(lái),另外,,基類(lèi)System.Object的成員GetType()和Equals()也被打印了出來(lái),。

有的時(shí)候,,我們可能不希望查看基類(lèi)的成員,也可能希望查看私有的成員,,此時(shí)可以使用GetMembers()的重載方法,,傳入 BindingFlags 位標(biāo)記參數(shù)來(lái)完成。BindingFlags位標(biāo)記對(duì)如何獲取成員的方式進(jìn)行控制(也可以控制如何創(chuàng)建對(duì)象實(shí)例,,后面會(huì)說(shuō)明),。對(duì)于本例,如果我們想獲取 所有的公有,、私有,、靜態(tài)、實(shí)例 成員,,那么只需要這樣修改GetMembers()方法就可以了,。

MemberInfo[] memberInfo = t.GetMembers(
    BindingFlags.Public |
    BindingFlags.Static |
    BindingFlags.NonPublic |
    BindingFlags.Instance |
    BindingFlags.DeclaredOnly
);

此時(shí)的輸出如下:

查看類(lèi)型 DemoClass的成員信息:
--------------------------------------------------
成員:Void add_myEvent(Demo.DemoDelegate)      類(lèi)型: Method
成員:Void remove_myEvent(Demo.DemoDelegate)   類(lèi)型: Method
成員:System.String get_Name()                 類(lèi)型: Method
成員:Void set_Name(System.String)             類(lèi)型: Method
成員:Void SayGreeting(System.String)          類(lèi)型: Method
成員:Void .ctor()                             類(lèi)型: Constructor
成員:System.String Name                       類(lèi)型: Property
成員:Demo.DemoDelegate myEvent                類(lèi)型: Event
成員:System.String name                        類(lèi)型: Field
成員:Demo.DemoDelegate myEvent                類(lèi)型: Field
成員:System.String text                       類(lèi)型: Field
成員:Demo.DemoClass+NestedClass               類(lèi)型: NestedType

可以看到,繼承自基類(lèi) System.Object 的方法都被過(guò)濾掉了,,同時(shí),,打印出了私有的 name, myEvent 等字段。

現(xiàn)在如果我們想要獲取所有的方法(Method),,那么我們可以使用 Type類(lèi)的FindMembers()方法:

MemberInfo[] memberInfo = t.FindMembers(
    MemberTypes.Method,      // 說(shuō)明查找的成員類(lèi)型為 Method
    BindingFlags.Public |
    BindingFlags.Static |
    BindingFlags.NonPublic |
    BindingFlags.Instance |
    BindingFlags.DeclaredOnly,
    Type.FilterName,
    "*"
);

Type.FilterName 返回一個(gè)MemberFilter類(lèi)型的委托,,它說(shuō)明按照方法名稱(chēng)進(jìn)行過(guò)濾,最后一個(gè)參數(shù)“*”,,說(shuō)明返回所有名稱(chēng)(如果使用“Get*”,,則會(huì)返回所有以Get開(kāi)頭的方法)。現(xiàn)在的輸出如下:

查看類(lèi)型 DemoClass的成員信息:
--------------------------------------------------
成員:Void add_myEvent(Demo.DemoDelegate)      類(lèi)型: Method
成員:Void remove_myEvent(Demo.DemoDelegate)   類(lèi)型: Method
成員:System.String get_Name()                 類(lèi)型: Method
成員:Void set_Name(System.String)             類(lèi)型: Method
成員:Void SayGreeting(System.String)          類(lèi)型: Method

MemberInfo 類(lèi)有兩個(gè)屬性值得注意,,一個(gè)是DeclaringType,,一個(gè)是 ReflectedType,返回的都是Type類(lèi)型,。DeclaredType 返回的是聲明該成員的類(lèi)型,。比如說(shuō),回顧我們之前的一段代碼:

MemberInfo[] members = typeof(DemoClass).GetMembers();

它將返回所有的公有成員,,包括繼承自基類(lèi)的Equals()等方法,,對(duì)于Equals()方法來(lái)說(shuō),它的 DeclaringType 返回的是相當(dāng)于 typeof(Object) 的類(lèi)型實(shí)例,,因?yàn)樗窃?System.Object中被定義的,;而它的ReflectedType 返回的則是相當(dāng)于 typeof(DemoClass) 類(lèi)型實(shí)例,因?yàn)樗峭ㄟ^(guò) DemoClass 的類(lèi)型實(shí)例被獲取的,。

3.字段信息 與 FieldInfo類(lèi)型

如同我們之前所說(shuō),,MemberInfo 是一個(gè)基類(lèi),它包含的是類(lèi)型的各種成員都公有的一組信息,。實(shí)際上,,對(duì)于字段,、屬性、方法,、事件 等類(lèi)型成員來(lái)說(shuō),,它們包含的信息顯然都是不一樣的,所以,,.Net 中提供了 FiledInfo 類(lèi)型來(lái)封裝字段的信息,,它繼承自MemberInfo。

如果我們希望獲取一個(gè)類(lèi)型的所有字段,,可以使用 GetFileds()方法,。我們?cè)俅翁砑右粋€(gè)方法FieldExplore():

public static void FieldExplore(Type t) {
    StringBuilder sb = new StringBuilder();
   
    FieldInfo[] fields = t.GetFields();

    sb.Append("查看類(lèi)型 " + t.Name + "的字段信息:\n");
    sb.Append(String.Empty.PadLeft(50, '-') + "\n");

    foreach (FieldInfo fi in fields) {
       sb.Append("名稱(chēng):" + fi.Name + "\n");
       sb.Append("類(lèi)型:" + fi.FieldType + "\n");
       sb.Append("屬性:" + fi.Attributes + "\n\n");
    }

    Console.WriteLine(sb.ToString());
}

產(chǎn)生的輸出如下:

查看類(lèi)型 DemoClass的字段信息:
--------------------------------------------------
名稱(chēng):city
類(lèi)型:System.String
屬性:Public

名稱(chēng):title
類(lèi)型:System.String
屬性:Public, InitOnly

名稱(chēng):text
類(lèi)型:System.String
屬性:Public, Static, Literal, HasDefault

值得一提的是fi.FieldType 屬性,它返回一個(gè)FieldAttributes位標(biāo)記,,這個(gè)位標(biāo)記包含了字段的屬性信息,。對(duì)比我們之前定義的DemoClass類(lèi),可以看到,,對(duì)于 title 字段,,它的屬性是public, InitOnly;對(duì)于Const類(lèi)型的text字段,,它的屬性為Public,Static,Literal,,HasDefault,由此也可以看出,, 聲明一個(gè)const類(lèi)型的變量,,它默認(rèn)就是靜態(tài)static的,同時(shí),,由于我們給了它初始值,,所以位標(biāo)記中也包括HasDefault。

針對(duì)于FieldType位標(biāo)記,,F(xiàn)iledInfo 類(lèi)提供了一組返回為bool類(lèi)型的屬性,,來(lái)說(shuō)明字段的信息,常用的有:IsPublic, IsStatic, IsInitOnly, IsLiteral, IsPrivate 等,。

如果我們想要獲取私有字段信息,依然可以使用重載了的GetFields[]方法,,傳入BindingFlags參數(shù),,和上面的類(lèi)似,這里就不重復(fù)了,。

4.屬性信息 與 PropertyInfo 類(lèi)型

和字段類(lèi)似,,也可以通過(guò) GetProperty()方法,獲取類(lèi)型的所有屬性信息,。

public static void PropertyExplore(Type t) {
    StringBuilder sb = new StringBuilder();
    sb.Append("查看類(lèi)型 " + t.Name + "的屬性信息:\n");
    sb.Append(String.Empty.PadLeft(50, '-') + "\n");

    PropertyInfo[] properties = t.GetProperties();

    foreach (PropertyInfo pi in properties) {
       sb.Append("名稱(chēng):" + pi.Name + "\n");
       sb.Append("類(lèi)型:" + pi.PropertyType + "\n");
       sb.Append("可讀:" + pi.CanRead + "\n");
       sb.Append("可寫(xiě):" + pi.CanWrite +"\n");
       sb.Append("屬性:" + pi.Attributes +"\n");
    }

    Console.WriteLine(sb.ToString());
}

輸出如下:

查看類(lèi)型 DemoClass的屬性信息:
--------------------------------------------------
名稱(chēng):Name
類(lèi)型:System.String
可讀:True
可寫(xiě):True
屬性:None

從前面的章節(jié)可以看到,,Name屬性會(huì)在編譯后生成Get_Name()和Set_Name()兩個(gè)方法,,那么,應(yīng)該可以利用反射獲取這兩個(gè)方法,。 PropertyInfo類(lèi)的GetGetMethod()和GetSetMethod()可以完成這個(gè)工作,,它返回一個(gè)MethodInfo對(duì)象,封裝 了關(guān)于方法的信息,,我們會(huì)在后面看到,。

5.方法信息 與 MethodInfo 類(lèi)型

與前面的類(lèi)似,我們依然可以編寫(xiě)代碼來(lái)查看類(lèi)型的方法信息,。

public static void MethodExplore(Type t) {
    StringBuilder sb = new StringBuilder();
    sb.Append("查看類(lèi)型 " + t.Name + "的方法信息:\n");
    sb.Append(String.Empty.PadLeft(50, '-') + "\n");

    MethodInfo[] methods = t.GetMethods();

    foreach (MethodInfo method in methods) {
       sb.Append("名稱(chēng):" + method.Name +"\n");
       sb.Append("簽名:" + method.ToString() + "\n");
       sb.Append("屬性:" + method.Attributes + "\n");
       sb.Append("返回值類(lèi)型:" + method.ReturnType + "\n\n");
    }

    Console.WriteLine(sb.ToString());
}

與前面類(lèi)似,,MethodInfo 類(lèi)也有一個(gè)Attributes屬性,它返回一個(gè)MethodAttribute,,MethodAttribute 位標(biāo)記標(biāo)明了方法的一些屬性,,常見(jiàn)的比如Abstract, Static, Virtual,Public, Private 等。

與前面不同的是,,Method可以具有參數(shù) 和 返回值,,MethodInfo 類(lèi)提供了 GetParameters() 方法獲取 參數(shù)對(duì)象的數(shù)組,方法的參數(shù)都封裝在了 ParameterInfo 類(lèi)型中,。查看ParameterInfo類(lèi)型的方法與前面類(lèi)似,,這里就不再闡述了。

6. ConstructorInfo類(lèi)型,、EventInfo 類(lèi)型

從名稱(chēng)就可以看出來(lái),,這兩個(gè)類(lèi)型封裝了類(lèi)型 的構(gòu)造函數(shù) 和 事件信息,大家都是聰明人,,查看這些類(lèi)型與之前的方法類(lèi)似,,這里就不再重復(fù)了。

7.小結(jié)

本文涉及了反射的最基礎(chǔ)的內(nèi)容,,我們可以利用反射來(lái)自頂向下地查看程序集,、模塊、類(lèi)型,、類(lèi)型成員的信息,。反射更強(qiáng)大、也更有意思的內(nèi)容:遲綁定方法,、動(dòng)態(tài)創(chuàng)建類(lèi)型以后會(huì)再講到,。

轉(zhuǎn)載地址:http://www./CLR-and-Framework/Reflection-Part2.aspx

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多