[.net 面向對象程式設計進階] (20) 反射(Reflection) 利用反射技術實現動態編程(上)

来源:http://www.cnblogs.com/yubinfeng/archive/2016/01/24/5154485.html
-Advertisement-
Play Games

主要介紹什麼是.NET反射特性,.NET反射能為我們做些什麼,最後介紹幾種常用的反射的實現方法,通過對反射性特的瞭解,可以設計出非常有用的基於反射的編程模式。


[.net 面向對象程式設計進階] (20) 反射(Reflection) 利用反射技術實現動態編程(上)

本節導讀:本節主要介紹什麼是.NET反射特性,.NET反射能為我們做些什麼,最後介紹幾種常用的反射的實現方法,通過對反射性特的瞭解,可以設計出非常有用的基於反射的編程模式。

讀前必備:

[.net 面向對象編程基礎]  (10) 類的成員(欄位、屬性、方法)

1.什麼是.NET反射?

反射是.NET一個重要的特性,《CLR via C#》一書中對.NET反射的解釋為:在我們應用程式中使用元數據來表示存儲。編譯程式集或模塊時,編譯器會創建一個類型定義表、一個欄位定義表、一個方法定義表以及其它表。而我們如果想動態調用這些元數據表(或說是解析這些表),或說是為這些元數據創建一個對象模型,這個過程就是反射。

簡單通俗的說,就是動態調用編譯過的程式集中的屬性,欄位,方法等的過程,就是反射。

反射在.NET,通過System.Reflection命名空間中的類來實現。

2.反射能為我們做些什麼?

這個問題是我們學習反射的重點,總得知道學習它的好處,才會繼續把本文看下去。

反射特性,確實是.NET一個非常重要且有用的特性。

A.枚舉類型成員

B.實例化新對象

C.執行對象成員

D.查找類型信息

E.查詢程式集信息

F.檢查應用於某種類型的自定義特性

G.創建和編譯新的程式集

H.簡化執行時而非編譯時綁定的數據的操作。(C# 4.0以後新功能)

此外.NET新版本中允許泛型上的反射.

以上是反射的基本特性,參考了《C#本質論》和《C#高級編程》

基於上面的基本特性,我們可以設計出很多非常實用的編程模式。

下麵列舉幾種基於反射設計模式下的實例:

A.利用反射創動態創建程式集的API文檔。基於反射允許枚舉程式集中類型及成員的特性,我們可以通過反射獲取已編譯的程式集中的欄位方法屬性事件和他們的XML註釋。從而動態創建程式集的API文檔;

B.非常常用的反射工廠模式。反射工廠模式在設計模式中比較容易理解,也比較簡單。很多代碼生成器中就利用這種設計模式完成不同資料庫的反射調用。比如我們有MsSqlMySqlOracle這三種資料庫,在項目設計中,我們有可能隨時換另一種資料庫(當然這隻是假設),因此需要同時實現這三種資料庫的基礎增刪改查的類即數據訪問類。我們要切換資料庫的時候,只需要在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;
        }
    }
}
View Code

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 "不知道";
            }
        }
    }
}
View Code

第二個項目調用如下:

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();
        }
    }
}
View Code

運行結果如下:

5.本節要點:

本節主要介紹和反射的用途及反射的基本操作類及屬性方法,下節繼續深入介紹如何將反射技術應用於實際項目之中。

==============================================================================================  

 返回目錄

 <如果對你有幫助,記得點一下推薦哦,如有

有不明白或錯誤之處,請多交流>  

<對本系列文章閱讀有困難的朋友,請先看《.net 面向對象編程基礎》>

<轉載聲明:技術需要共用精神,歡迎轉載本博客中的文章,但請註明版權及URL>

.NET 技術交流群:467189533    .NET 程式設計

==============================================================================================   


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 所謂的處理器就是電腦的核心運算硬體,現在使用windows操作系統的用戶使用的機器之中的處理器多數都是X86內核,而實際之上很多時候我們用戶都是會在心目之中把一個處理器和其運行的特定操作系統掛鉤,之前說的X86和windows操作系統,而在Cortex-A系列硬體之上我們運行的多數都是Androi...
  • 1,使用工具概述 FT232Rl晶元+sscom32+示波器 2,接收數據分析 sscom32發送數據:0xaa[1010 1010] 波特率為:4800bps @5V系統 示波器測試FT232RL 發送引腳 Txd,得到數據如上圖所示。 從上圖中可以得到如下幾點結論: 1.Txd空閑為高電平。 2...
  • 1.修改主機名及hosts文件10.205.22.185 nn1 (主)作用namenode,resourcemanager,datanode,zk,hive,sqoop10.205.22.186 nn2 (備)作用namenode,resourcemanager,datanode,zk10.205...
  • BBB 的板上有五個 LED 燈,一個電源,四個其他指示燈,usr0 至 usr3 。這次學習是控制 usr0 至 3 讓它們亮著,熄滅,閃。算是個 Hello World 實驗。非常簡單。 需要的材料: BBB 一臺 購買BBB 自帶的數據線一條 手提電腦或台式電腦,有 USB 插頭的 首先用數據...
  • 由於Python易學、開源、面向對象、可移植性高、庫豐富的特點,近期開始學習Python。百度瞭解了各款Python IDE後,還是認為Eric比較適合我,所以踏上了安裝Eric坎坷之路,從選定工具到安裝成功一共花費了8天時間,從Windows到Linux再到Mac,挨個折騰了一遍,Windows的...
  • 問題一:什麼是C#?C#是微軟公司在2000年新推出的一款運行在.NET Framework平臺上面的編程語言,這個.NET Framework平臺又怎麼去理解呢?舉個例子來說好了,一個土著族人只會說土著話,他跑到美國去用土著話跟別人交流,別人當然什麼都聽不懂,最後他還是乖乖回到他的土著國。那麼在這...
  • 此文主要分享瞭如何將自己博客園的文章自動導出到 Markdown 文檔進行存儲,以便在本地進行歸檔管理,程式中也對文章的分類、tag、代碼塊以及文章中的圖片進行了保存處理,以便上傳到自己的圖床。
  • 第11章函數函數提供了一個有力代碼復用機制, 並且讓你的代碼保持簡潔和易懂。它們同樣也是EF運行時能利用的資料庫層代碼.函數有幾類: Rowset Functions, 聚合函數, Ranking Functions, 和標量值函數.函數要麼確定,要麼不確定。當用一些指定的值調用函數,而函數返回的結...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...