[.net 面向對象程序設計進階] (20) 反射(Reflection)(上)利用反射技術實現動態編程html
本節導讀:本節主要介紹什麼是.NET反射特性,.NET反射能爲咱們作些什麼,最後介紹幾種經常使用的反射的實現方法,經過對反射性特的瞭解,能夠設計出很是有用的基於反射的編程模式。數據庫
讀前必備:編程
[.net 面向對象編程基礎] (10) 類的成員(字段、屬性、方法)設計模式
1.什麼是.NET反射?ide
反射是.NET一個重要的特性,《CLR via C#》一書中對.NET反射的解釋爲:在咱們應用程序中使用元數據來表示存儲。編譯程序集或模塊時,編譯器會建立一個類型定義表、一個字段定義表、一個方法定義表以及其它表。而咱們若是想動態調用這些元數據表(或說是解析這些表),或說是爲這些元數據建立一個對象模型,這個過程就是反射。函數
簡單通俗的說,就是動態調用編譯過的程序集中的屬性,字段,方法等的過程,就是反射。學習
反射在.NET,經過System.Reflection命名空間中的類來實現。spa
2.反射能爲咱們作些什麼?.net
這個問題是咱們學習反射的重點,總得知道學習它的好處,纔會繼續把本文看下去。設計
反射特性,確實是.NET一個很是重要且有用的特性。
A.枚舉類型成員
B.實例化新對象
C.執行對象成員
D.查找類型信息
E.查詢程序集信息
F.檢查應用於某種類型的自定義特性
G.建立和編譯新的程序集
H.簡化執行時而非編譯時綁定的數據的操做。(C# 4.0之後新功能)
此外.NET新版本中容許泛型上的反射.
以上是反射的基本特性,參考了《C#本質論》和《C#高級編程》
基於上面的基本特性,咱們能夠設計出不少很是實用的編程模式。
下面列舉幾種基於反射設計模式下的實例:
A.利用反射創動態建立程序集的API文檔。基於反射容許枚舉程序集中類型及成員的特性,咱們能夠經過反射獲取已編譯的程序集中的字段方法屬性事件和他們的XML註釋。從而動態建立程序集的API文檔;
B.很是經常使用的反射工廠模式。反射工廠模式在設計模式中比較容易理解,也比較簡單。不少代碼生成器中就利用這種設計模式完成不一樣數據庫的反射調用。好比咱們有MsSql、MySql、Oracle這三種數據庫,在項目設計中,咱們有可能隨時換另外一種數據庫(固然這只是假設),所以須要同時實現這三種數據庫的基礎增刪改查的類即數據訪問類。咱們要切換數據庫的時候,只須要在config中更改數據庫類型,其餘的工做交給反射工廠類去動態調用編譯好的程序集中對應的數據庫訪問方法。
若是沒有理解也不要緊,這裏只是說明一下反射的應用實例,以便於更有信心的學習反射。反射在設計模式中的應還有不少,這裏再也不列舉。
3.反射應用基礎
上面說了這麼多,無非就是先讓咱們理解反射能爲咱們作些什麼,下面進入正題,說一下反射的代碼實現。
下面主要介紹反射的核心類及類成員
反射的命名空間:System.Reflection
反射的類大多都在這個命名空間中。
主要的類: System.Type
這個類是反射的核心,其屬性方法能夠獲得運行時的信息。
Type類派生於System.Reflection.MemberInfo抽象類
MemberInfo類中的只讀屬性 |
||
屬性 |
描述 |
備註 |
Type DeclaringType |
獲取聲明該成員的類或接口的類型 |
|
MemberTypes MemberType |
獲取成員的類型,這個值用於指示該成員是字段、方法、屬性、事件、或構造函數 |
這是一個枚舉,它定義了用於表示不一樣成員的類型值。這些值包括:MemberTypes.Constructor, MemberTypes.Method, MemberTypes.Field, MemberTypes.Event, MemberTypes.Property。所以能夠經過檢查MemberType屬性來肯定成員的類型,例如,在MemberType屬性的值爲MemberTypes.Method時,該成員爲方法 |
Int MetadataToken |
獲取與特定元數據相關的值 |
|
Module Module |
獲取一個表明反射類型所在模塊(可執行文件)的Module對象 |
|
String Name |
成員的名稱 |
|
Type ReflectedType |
反射的對象類型 |
|
Type類的只讀屬性 |
|
屬性 |
描述 |
Assembly Assembly |
獲取指定類型的程序集 |
TypeAttributes Attributes |
獲取制定類型的特性 |
Type BaseType |
獲取指定類型的直接基類型 |
String FullName |
獲取指定類型的全名 |
bool IsAbstract |
若是指定類型是抽象類型,返回true |
bool IsClass |
若是指定類型是類,返回true |
string Namespace |
獲取指定類型的命名空間 |
Type類的方法 |
|
方法 |
描述 |
ConstructorInfo[] GetConstructors() |
獲取指定類型的構造函數列表 |
EventInfo[] GetEvents(); |
獲取指定類型的時間列 |
FieldInfo[] GetFields(); |
獲取指定類型的字段列 |
Type[] GetGenericArguments(); |
獲取與已構造的泛型類型綁定的類型參數列表,若是指定類型的泛型類型定義,則得到類型形參。對於正早構造的類型,該列表就可能同時包含類型實參和類型形 |
MethodInfo[] GetMethods(); |
獲取指定類型的方法列表 |
PropertyInfo[] GetProperties(); |
獲取指定類型的屬性列表e |
MemberInfo[] GetMembers(); |
獲取指定類型的成員列表 |
反射還有不少類,這裏不一一介紹,詳細能夠查閱MSDN:
https://msdn.microsoft.com/zh-cn/library/system.reflection.aspx
4.反射實例
下面經過一個實例來學習一下反射最基本的使用方法。
創建一個解決方案,包含兩個項目,項目ClassLibrary生成一個DLL(包含兩個類),另外一個項目是ReflectionTestGet,用於反射調用類ClassLibrary
第一個項目的兩個類以下:
MartialArtsMaster.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ClassLibrary { /// <summary> /// 類:武林高手 /// MartialArtsMaster /// </summary> class MartialArtsMaster { /// <summary> /// 級別 /// </summary> public int _level = 9; /// <summary> /// 編號 /// </summary> public int Id { get; set; } /// <summary> /// 姓名 /// </summary> public string Name { get; set; } /// <summary> /// 年齡 /// </summary> public int Age { get; set; } /// <summary> /// 門派 /// </summary> public string Menpai { get; set; } /// <summary> /// 武學 /// </summary> public string Kungfu { get; set; } /// <summary> /// 級別 /// </summary> public int Level { get { return _level; } set { _level = value; } } /// <summary> /// 攻擊 /// </summary> /// <param name="kungfu"></param> /// <returns></returns> public string Attack(string kungfu) { return "使用用了功夫:" + kungfu; } public string Kill(string kungfu, string name) { return "使用用了功夫:" + kungfu + "擊殺了" + name; } } }
Person.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ClassLibrary { /// <summary> /// 類:人 /// </summary> class Person { public string gender { get; set; } public string race { get; set; } public string Country { get; set; } public string Eat(string strCountry) { switch (strCountry) { case "美國": return "愛吃西餐"; case "韓國": return "愛吃泡菜"; default: return "不知道"; } } } }
第二個項目調用以下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; namespace ReflectionTestGet { class Program { static void Main(string[] args) { Assembly asm = Assembly.LoadFrom("ClassLibrary.dll"); //加載指定的程序集 Type[] alltype = asm.GetTypes(); //獲取程序集中的全部類型列表 foreach (Type calssName in alltype) { Console.WriteLine("加載程序的集類名:"+ calssName.Name); //打印出程序集全部類 foreach (var field in calssName.GetFields()) Console.WriteLine(calssName.Name+"字段有:" + field.Name); //打印出程序集全部字段,注意只能獲取公有字段 foreach (var pro in calssName.GetProperties()) Console.WriteLine(calssName.Name + "屬性有:" + pro.Name); //打印出程序集全部屬性 foreach (var met in calssName.GetMethods()) Console.WriteLine(calssName.Name + "方法有:" + met.Name); //打印出程序集全部方法 } Console.ReadKey(); } } }
運行結果以下:
5.本節要點:
本節主要介紹和反射的用途及反射的基本操做類及屬性方法,下節繼續深刻介紹如何將反射技術應用於實際項目之中。
==============================================================================================
<若是對你有幫助,記得點一下推薦哦,若有
有不明白或錯誤之處,請多交流>
<對本系列文章閱讀有困難的朋友,請先看《.net 面向對象編程基礎》>
<轉載聲明:技術須要共享精神,歡迎轉載本博客中的文章,但請註明版權及URL>
==============================================================================================