C#之反射

来源:http://www.cnblogs.com/afei-24/archive/2017/05/17/6867986.html
-Advertisement-
Play Games

C#反射技術主要基於System.Type類和System.Reflection.Assemble類,通過Type類可以訪問關於任何數據類型的信息,Assemble類用於訪問給定程式集的相關信息,或把這個程式集載入到程式中。 一.System.Type類 Type類是一個抽象類。只要實例化了一個Ty ...


  C#反射技術主要基於System.Type類和System.Reflection.Assemble類,通過Type類可以訪問關於任何數據類型的信息,Assemble類用於訪問給定程式集的相關信息,或把這個程式集載入到程式中。

一.System.Type類
  Type類是一個抽象類。只要實例化了一個Type對象,實際上就實例化了Type的一個派生類。儘管一般情況下派生類只提供各種Type方法和屬性的不同重載,但是這些方法和屬性返回對應數據類型的正確數據,Type有與每種數據類型對應的派生類。它們一般不添加新的方法或屬性
  通常,獲取指向任何給定的Type引用有三種常用方式:
    *使用typeof運算符,這個運算符的參數是類型的名稱,但不放在引號中:
      Type t =typeof(double);
    *使用GetType()方法,所以類都會從System.Object繼承這個方法:
      double d =10;
      Type t = d.GetType();
      在一個變數上調用GetType()方法,返回的Type對象只與該數據類型相關,不包含該類型實例的任何信息。
    *調用Type類的靜態方法GetType():
      Type t =Type.GetType("System.Double");

  Type是很多反射功能的入口,它實現很多方法和屬性,可用的屬性都是只讀的:可以使用Type確定數據的類型,但不能使用它修改該類型。

  1.Type屬性
  由Type實現的屬性分為3類。
  *包含與類相關的各種名稱的字元串:
    Name:數據類型名
    FullName:數據類型的完全限定名(包含名稱空間)
    Namespace:在其中定義數據類型的名稱空間名
  *獲取Type對象的引用的屬性:
    BaseType:該對象的直接基本類型
    UnderlyingSystemType:該Type在.NET運行庫中映射到的類型
  *布爾屬性
    IsAbstract,IsArray,IsClass,IsEnum等判斷Type是什麼類型的屬性。

  2.方法
  System.Type的大多數方法都用於獲取對應數據類型的成員信息:構造函數,屬性,方法和事件等。它有許多方法,但它們都有相同的模式。例如,獲取數據類型的方法的信息:GetMethod()和GetMethods()。GetMethod()方法返回MethodInfo對象的一個引用,其中包含一個指定方法的細節信息;而GetMethods()返回這種引用的一個數組。


二.Assembly類
  Assembly類允許訪問給定程式集的元數據,它也包含可以載入和執行程式集(假定該程式集是可執行的)的方法。與Type類一樣,Assembly類包含非常多的方法和屬性,這裡只介紹與特性(http://www.cnblogs.com/afei-24/p/6867935.html)有關的成員,其它成員可以去MSDN(https://msdn.microsoft.com/zh-cn/library/system.reflection.assembly(v=vs.100).aspx)查看。
  

  

  

  在使用Assembly實例做一些工作前,需要把相應的程式集載入到正在運行的進程中。可以使用靜態方法Assembly.Load()或Assembly.LoadFrom()。Load()方法的參數程式集的名稱,運行庫會在各個位置上搜索該程式集,這些位置包括本地目錄和全局程式集緩存。而LoadFrom()方法的參數是程式集的完整路徑名,它不會在其它位置搜索該程式集:
  Assembly assembly1 = Assembly.Load(“WhatsNewAttributes");
  Assembly assembly2 = Assembly.LoadFrom(“E:\WhatsNewAttributes\bin\Debug\WhatsNewAttributes");
  這兩個方法都有許多其它重載版本。

  1.獲取在程式集中定義的類型的詳細信息
  Assembly類調用GetType()方法可以獲得相應程式集中定義的所有類型的詳細信息,它返回一個包含所有類型的詳細信息的System.Type引用數組:
    Type[] types = assembly1.GetType();

    foreach(Type t in types)
    {

    }

  2.獲取自定義特性的詳細信息
  如果需要確定程式集關聯了什麼自定義特性,就需要調用Attribute類的一個靜態方法GetCustomAttributes():
    Assembly assembly1 = Assembly.Load(“WhatsNewAttributes");
    Attribute[] attribs = Attribute.GetCustomAttributes(assembly1);
  GetCustomAttributes方法用於獲取程式集的特性,他有兩個重載方法:如果在調用它時,除了程式集的引用外,沒有其它參數,該方法就會返回這個程式集定義的所以自定義特性;如果指定第二個參數,第二個參數表示特性類的一個Type對象,GetCustomAttributes方法返回指定特性類型的特性數組。
  所有的特性都作為一般的Attribute引用來獲取。如果需要調用為自定義特性定義的任何方法或屬性,就需要把這些引用顯示轉換為自定義特性類。
  如果要獲得與方法,構造函數和欄位等的特性,就需要調用MethodInfo,ConstructorInfo,FieldInfo等類的GetCustomAttributes()方法。

  下麵通過一個例子演示,自定義特性和反射
  1.編寫自定義特性

  namespace WhatsNewAttributes
    {
        [AttributeUsage(
            AttributeTargets.Class | AttributeTargets.Method,
            AllowMultiple = true, Inherited = false)]
        public class LastModifiedAttribute : Attribute
        {
            private readonly DateTime _dateModified;
            private readonly string _changes;

            public LastModifiedAttribute(string dateModified, string changes)
            {
                _dateModified = DateTime.Parse(dateModified);
                _changes = changes;
            }

            public DateTime DateModified
            {
                get { return _dateModified; }
            }

            public string Changes
            {
                get { return _changes; }
            }

            public string Issues { get; set; }
        }

        [AttributeUsage(AttributeTargets.Assembly)]
        public class SupportsWhatsNewAttribute : Attribute
        {
        }
    }

 

 

  2.對VectorClass和其成員使用自定義特性

  [assembly: SupportsWhatsNew]

    namespace VectorClass
    {
        [LastModified("14 Feb 2010", "IEnumerable interface implemented " +
                                     "So Vector can now be treated as a collection")]
        [LastModified("10 Feb 2010", "IFormattable interface implemented " +
                                     "So Vector now responds to format specifiers N and VE")]
        class Vector : IFormattable, IEnumerable
        {
            public double x, y, z;

            public Vector(double x, double y, double z)
            {
                this.x = x;
                this.y = y;
                this.z = z;
            }

            [LastModified("10 Feb 2010", "Method added in order to provide formatting support")]
            public string ToString(string format, IFormatProvider formatProvider)
            {
                if (format == null)
                    return ToString();
                string formatUpper = format.ToUpper();
                switch (formatUpper)
                {
                    case "N":
                        return "|| " + Norm().ToString() + " ||";
                    case "VE":
                        return String.Format("( {0:E}, {1:E}, {2:E} )", x, y, z);
                    case "IJK":
                        StringBuilder sb = new StringBuilder(x.ToString(), 30);
                        sb.Append(" i + ");
                        sb.Append(y.ToString());
                        sb.Append(" j + ");
                        sb.Append(z.ToString());
                        sb.Append(" k");
                        return sb.ToString();
                    default:
                        return ToString();
                }
            }

            public Vector(Vector rhs)
            {
                x = rhs.x;
                y = rhs.y;
                z = rhs.z;
            }

            [LastModified("14 Feb 2010", "Method added in order to provide collection support")]
            public IEnumerator GetEnumerator()
            {
                return new VectorEnumerator(this);
            }

            public override string ToString()
            {
                return "( " + x + " , " + y + " , " + z + " )";
            }

            public double this[uint i]
            {
                get
                {
                    switch (i)
                    {
                        case 0:
                            return x;
                        case 1:
                            return y;
                        case 2:
                            return z;
                        default:
                            throw new IndexOutOfRangeException(
                                "Attempt to retrieve Vector element" + i);
                    }
                }
                set
                {
                    switch (i)
                    {
                        case 0:
                            x = value;
                            break;
                        case 1:
                            y = value;
                            break;
                        case 2:
                            z = value;
                            break;
                        default:
                            throw new IndexOutOfRangeException(
                                "Attempt to set Vector element" + i);
                    }
                }
            }

            public static bool operator ==(Vector lhs, Vector rhs)
            {
                if (System.Math.Abs(lhs.x - rhs.x) < double.Epsilon &&
                    System.Math.Abs(lhs.y - rhs.y) < double.Epsilon &&
                    System.Math.Abs(lhs.z - rhs.z) < double.Epsilon)
                    return true;
                else
                    return false;
            }

            public static bool operator !=(Vector lhs, Vector rhs)
            {
                return !(lhs == rhs);
            }

            public static Vector operator +(Vector lhs, Vector rhs)
            {
                Vector result = new Vector(lhs);
                result.x += rhs.x;
                result.y += rhs.y;
                result.z += rhs.z;
                return result;
            }

            public static Vector operator *(double lhs, Vector rhs)
            {
                return new Vector(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
            }

            public static Vector operator *(Vector lhs, double rhs)
            {
                return rhs * lhs;
            }

            public static double operator *(Vector lhs, Vector rhs)
            {
                return lhs.x * rhs.x + lhs.y + rhs.y + lhs.z * rhs.z;
            }

            public double Norm()
            {
                return x * x + y * y + z * z;
            }

            #region enumerator class
            [LastModified("14 Feb 2010", "Class created as part of collection support for Vector")]
            private class VectorEnumerator : IEnumerator
            {
                readonly Vector _theVector;      // Vector object that this enumerato refers to 
                int _location;   // which element of _theVector the enumerator is currently referring to 

                public VectorEnumerator(Vector theVector)
                {
                    _theVector = theVector;
                    _location = -1;
                }

                public bool MoveNext()
                {
                    ++_location;
                    return (_location > 2) ? false : true;
                }

                public object Current
                {
                    get
                    {
                        if (_location < 0 || _location > 2)
                            throw new InvalidOperationException(
                                "The enumerator is either before the first element or " +
                                "after the last element of the Vector");
                        return _theVector[(uint)_location];
                    }
                }

                public void Reset()
                {
                    _location = -1;
                }

            }
            #endregion
        }
    }

  3.通過反射獲取程式集VectorClass和其成員的自定義特性

namespace LookUpWhatsNew
    {
        internal class WhatsNewChecker
        {
            private static readonly StringBuilder outputText = new StringBuilder(1000);
            private static DateTime backDateTo = new DateTime(2010, 2, 1);

            private static void Main()
            {
                Assembly theAssembly = Assembly.Load("VectorClass");
                Attribute supportsAttribute =
                    Attribute.GetCustomAttribute(
                        theAssembly, typeof (SupportsWhatsNewAttribute));
                string name = theAssembly.FullName;

                AddToMessage("Assembly: " + name);
                if (supportsAttribute == null)
                {
                    AddToMessage(
                        "This assembly does not support WhatsNew attributes");
                    return;
                }
                else
                {
                    AddToMessage("Defined Types:");
                }
                
                Type[] types = theAssembly.GetTypes();
                foreach (Type definedType in types)
                    DisplayTypeInfo(definedType);

                MessageBox.Show(outputText.ToString(),
                                "What\'s New since " + backDateTo.ToLongDateString());
                Console.ReadLine();
            }

            private static void DisplayTypeInfo(Type type)
            {
                // make sure we only pick out classes
                if (!(type.IsClass))
                    return;
                AddToMessage("\nclass " + type.Name);

                Attribute[] attribs = Attribute.GetCustomAttributes(type);
                if (attribs.Length == 0)
                    AddToMessage("No changes to this class");
                else
                    foreach (Attribute attrib in attribs)
                        WriteAttributeInfo(attrib);

                MethodInfo[] methods = type.GetMethods();
                AddToMessage("CHANGES TO METHODS OF THIS CLASS:");
                foreach (MethodInfo nextMethod in methods)
                {
                    object[] attribs2 =
                        nextMethod.GetCustomAttributes(
                            typeof (LastModifiedAttribute), false);
                    if (attribs2 != null)
                    {
                        AddToMessage(
                            nextMethod.ReturnType + " " + nextMethod.Name + "()");
                        foreach (Attribute nextAttrib in attribs2)
                            WriteAttributeInfo(nextAttrib);
                    }
                }
            }

            private static void WriteAttributeInfo(Attribute attrib)
            {
                LastModifiedAttribute lastModifiedAttrib =
                    attrib as LastModifiedAttribute;
                if (lastModifiedAttrib == null)
                    return;

                // check that date is in range
                DateTime modifiedDate = lastModifiedAttrib.DateModified;
                if (modifiedDate < backDateTo)
                    return;

                AddToMessage("  MODIFIED: " +
                             modifiedDate.ToLongDateString() + ":");
                AddToMessage("    " + lastModifiedAttrib.Changes);
                if (lastModifiedAttrib.Issues != null)
                    AddToMessage("    Outstanding issues:" +
                                 lastModifiedAttrib.Issues);
            }

            private static void AddToMessage(string message)
            {
                outputText.Append("\n" + message);
            }
        }
    }

 


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

-Advertisement-
Play Games
更多相關文章
  • 關於這三個關鍵字之前可以研究一下原本的一些操作 觀察運行結果發現 值並沒有被改變,也就是說此時的操作的原理可能也是跟以前C語言的函數操作是一樣的 本文主要討論params關鍵字,ref關鍵字,out關鍵字。 1)params關鍵字,官方給出的解釋為用於方法參數長度不定的情況。有時候不能確定一個方法的 ...
  • 1. 前言 這篇文章介紹了繼承並自定義Shape的方法,不過,恐怕,事實上,100個xaml的程式員99個都不會用到。寫出來是因為反正都學了,當作寫個筆記。 通過這篇文章,你可以學到如下知識點: 自定義Shape。 DeferRefresh模式。 InvalidateArrange的應用。 2. 從 ...
  • 先安裝改js包 主頁面的代碼主頁文件代碼Index.cshtml ...
  • C#包含四種訪問修飾符以及一種組合修飾符: public:訪問不受限制。 protected:訪問僅限於包含類或從包含類派生的類型。 internal:訪問僅限於當前程式集。 private:訪問僅限於包含類型。 protected internal:訪問限制到當前程式集或從包含派生的類型的類別。 ...
  • 使用php的生成圖片驗證碼,有效避免機器訪問,減輕伺服器資源消耗 ...
  • public const int BM_CLICK = 0x00F5; public const int WM_SETTEXT = 0x000C; /// /// 判斷視窗是否啟用 /// /// /// [DllImport("user32.dll")] [... ...
  • 在wpf的綁定中,我們會用到多值綁定,如下: 這裡如果 StringFormat="{3}({0}/{1}):{2}"這樣寫是不能通過編譯器的,解決方案是在前面加一組大括弧就可以了,如下: StringFormat="{}{3}({0}/{1}):{2}" 完整綁定如下: ... ...
  • 6.1 類型的各種成員 6.2 類型的可見性 public 全部可見 internal 程式集內可見(如忽略,預設為internal) 可通過設定 友元程式集 ,允許其它程式集訪問該程式集中的所有internal 類型.例如想允許強命名"Microsoft"程式集訪問本程式集內的internal類型 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...