淺析.NET的反射特性

来源:http://www.cnblogs.com/pengze0902/archive/2016/10/22/5986504.html
-Advertisement-
Play Games

在.net框架體系內,反射特性較多的應用到。反射的相關定義分為兩種。 自然解釋:射是一種自然現象,表現為受刺激物對刺激物的逆反應;這是反射的字面解釋,我們看一下電腦編程中的反射; 編程解釋:通過 System.Reflection 命名空間中的類以及 System.Type,您可以獲取有關已載入的 ...


     在.net框架體系內,反射特性較多的應用到。反射的相關定義分為兩種。

     自然解釋:射是一種自然現象,表現為受刺激物對刺激物的逆反應;這是反射的字面解釋,我們看一下電腦編程中的反射;

     編程解釋:通過 System.Reflection 命名空間中的類以 System.Type您可以獲取有關已載入的程式集和在其中定義的類型(如介面值類型)的信息。 您也可以使用反射在運行時創建類型實例,以及調用和訪問這些實。

     反射(Reflection)有下列用途:它允許在運行時查看屬性(attribute)信息;它允許審查集合中的各種類型,以及實例化這些類型;它允許延遲綁定的方法和屬性(property);它允許在運行時創建新類型,然後使用這些類型執行一些任務。

     下麵介紹一下有關反射的程式集的相關屬性和方法的源碼:

        (1).Object的GetType()方法:

    // Returns a Type object which represent this object instance.
    // 
    [System.Security.SecuritySafeCritical]  // auto-generated
    [Pure]
    [ResourceExposure(ResourceScope.None)]
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    public extern Type GetType();

      (2).PropertyInfo的GetProperty()方法:

 public PropertyInfo GetProperty(String name,BindingFlags bindingAttr,Binder binder, 
                        Type returnType, Type[] types, ParameterModifier[] modifiers)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (types == null)
                throw new ArgumentNullException("types");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,bindingAttr,binder,returnType,types,modifiers);
        }

        public PropertyInfo GetProperty(String name, Type returnType, Type[] types,ParameterModifier[] modifiers)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (types == null)
                throw new ArgumentNullException("types");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,types,modifiers);
        }

        public PropertyInfo GetProperty(String name, BindingFlags bindingAttr)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,bindingAttr,null,null,null,null);
        }

        public PropertyInfo GetProperty(String name, Type returnType, Type[] types)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (types == null)
                throw new ArgumentNullException("types");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,types,null);
        }

        public PropertyInfo GetProperty(String name, Type[] types)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (types == null)
                throw new ArgumentNullException("types");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,null,types,null);
        }

        public PropertyInfo GetProperty(String name, Type returnType)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (returnType == null)
                throw new ArgumentNullException("returnType");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,null,null);
        }

        internal PropertyInfo GetProperty(String name, BindingFlags bindingAttr, Type returnType)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (returnType == null)
                throw new ArgumentNullException("returnType");
            Contract.EndContractBlock();
            return GetPropertyImpl(name, bindingAttr, null, returnType, null, null);
        }

        public PropertyInfo GetProperty(String name)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,null,null,null);
        }

   (3).Object的GetValue()方法:

[DebuggerStepThroughAttribute]
        [Diagnostics.DebuggerHidden]
        public Object GetValue(Object obj)
        {
            return GetValue(obj, null);
        }

        [DebuggerStepThroughAttribute]
        [Diagnostics.DebuggerHidden]
        public virtual Object GetValue(Object obj,Object[] index)
        {
            return GetValue(obj, BindingFlags.Default, null, index, null);
        }

        public abstract Object GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture);

  以上介紹了一下有關反射的相關方法的底層方法源碼,現在介紹一下較為通用的方法:

    (1).獲取對象的所有公共屬性。

        /// <summary>
        /// 獲取對象的所有公共屬性。
        /// </summary>
        /// <param name="obj">定義該方法的數據類型。</param>
        /// <returns>返回包含該對象的屬性信息的數組。</returns>
        public static IEnumerable<PropertyInfo> GetProperties(this object obj)
        {
            return obj.GetType().GetProperties();
        }

    (2).獲取一個對象的屬性。

        /// <summary>
        ///獲取一個對象的屬性。
        /// </summary>
        /// <param name="obj">定義該方法的數據類型。gb</param>
        /// <param name="flags">提供要確定要檢索的屬性的標誌。</param>
        /// <returns>返回包含該對象的屬性信息的數組。</returns>
        public static IEnumerable<PropertyInfo> GetProperties(this object obj, BindingFlags flags)
        {
            return obj.GetType().GetProperties(flags);
        }

    (3).用指定名稱獲取具有指定名稱的屬性的當前對象的屬性值。

        /// <summary>
        ///用指定名稱獲取具有指定名稱的屬性的當前對象的屬性值。
        /// </summary>
        /// <param name="obj">要檢索的屬性值的對象。</param>
        /// <param name="propertyName">要檢索的屬性的名稱。</param>
        /// <returns>返回屬性的值。</returns>
        public static object GetPropertyValue(this object obj, string propertyName)
        {
            var item = obj.GetType().GetProperty(propertyName);

            if (item == null) return null;
            var value = obj.GetType().GetProperty(propertyName).GetValue(obj);

            if (item.PropertyType.IsGenericType)
            {
                value = item.PropertyType.GetProperty(propertyName);
            }
            return value;
        }

     (4).獲取一個枚舉字元串值。

        /// <summary>
        ///獲取一個枚舉字元串值。
        /// </summary>
        /// <param name="obj">該枚舉返回的字元串值。</param>
        /// <returns>返回一個枚舉字元串值。</returns>
        public static string GetStringValue(this System.Enum obj)
        {
            var fieldInfo = obj.GetType().GetField(obj.ToString());
            var attributes = fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];

            var output = (StringValueAttribute)attributes.GetValue(0);

            return output.Text;
        }

     (5).獲取方法調用。

        /// <summary>
        /// 獲取方法調用
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <returns></returns>
        public static MethodCallExpression GetMethodCall<T>(Expression<T>  action )
        {
            var call = action.Body as MethodCallExpression;

            return call;
        }

    (6).獲取類型名稱.

        /// <summary>
        /// 獲取類型名稱
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static string GetTypeName<T>()
        {
            return typeof (T).Name;
        }

    (7).獲取參數值

        /// <summary>
        /// 獲取參數值
        /// </summary>
        /// <param name="methodCall"></param>
        /// <returns></returns>
        public static IEnumerable<Tuple<ParameterInfo, object>> GetArgumentValues(MethodCallExpression methodCall)
        {
            var parameters = methodCall.Method.GetParameters();
            if (!parameters.Any()) yield break;
            for(var i = 0; i < parameters.Length; i++)
            {
                var arg = methodCall.Arguments[i];

                var ceValue = arg as ConstantExpression;

                if (ceValue != null)
                    yield return new Tuple<ParameterInfo, object>(parameters[i], ceValue.Value);
                else
                    yield return new Tuple<ParameterInfo, object>(parameters[i], GetExpressionValue(arg));
            }
        }

    (8).獲取表達式值

        /// <summary>
        /// 獲取表達式值
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private static object GetExpressionValue(Expression expression)
        {
            var lambda = Expression.Lambda<Func<object>>(Expression.Convert(expression, typeof (object)));
            var func = lambda.Compile();
            return func();
        }

    反射類的繼承層次如下:

      System.reflection  

      System.Reflection.Assembly 

  System.Reflection.MemberInfo
  System.Reflection.EventInfo
  System.Reflection.FieldInfo
  System.Reflection.MethodBase
  System.Reflection.ConstructorInfo
  System.Reflection.MethodInfo
  System.Reflection.PropertyInfo
  System.Type   

 


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

-Advertisement-
Play Games
更多相關文章
  • 一、說明 安裝環境 centos6.6 (64位) python2.7.10 (升級系統預設python版本的方法參見 "在CentOS 6.5上安裝python2.7" ) 約定 工作目錄假定為當前用戶的HOME目錄 安裝的各軟體版本以文檔編寫時的最新版為基準,請結合實際情況參考。 尖括弧""包括 ...
  • 簡介 ABP提供了一個緩存介面,它內部使用了這個緩存介面。雖然介面的預設實現是MemoryCache,但可以用任何其它實現的緩存供應器。Abp.RedisCache包用Redis實現了緩存(查看下方的“Redis 緩存集成”)。 ICacheManager 緩存的主要介面是ICacheManager ...
  • MySqlSugar 3.X API 作為支持.NET CORE 為數不多的ORM之一,除了具有優越的性能外,還擁有強大的功能,不只是滿足你的增,刪,查和改。實質上擁有更多你想像不到的功能,當你需要實現某個功能時會發現有這個功能太棒了。 所有版本 ASP.NET 4.0+ MSSQL https:/ ...
  • 作為物聯網通訊框架,肯定要支持多種通訊鏈路,在多種通訊鏈路的基礎上完成多種通訊協議的交互,例如:Modbus、自定義協議等等。但是,有一個問題:針對同一臺硬體設備或感測器,完成串口和網路兩種通訊方式的數據採集和控制,是否要分別寫代碼?如果從現實角度分析,同一硬體,它要完成的業務邏輯肯定是相同的,所以... ...
  • 代碼是敲出來的嗎?是批量生成出來的嗎? No no no,代碼是設計出來的! 如果說到代碼生成器,大家可能會想到三層、動軟代碼生成器、資料庫表等等。其一般的思路是,先有資料庫然後根據庫里的表自動生成一系列的代碼,包括實體類、持久化、業務層(空函數)、頁面代碼等,還可以生成資料庫文檔。這個確實很好很強 ...
  • 文檔目錄 本節內容: 簡介 關於 IAbpSeesion 註入會話 會話屬性 用戶標識符 關於 IAbpSeesion 簡介 如果一個應用需要登錄,它就需要知道當前用戶在執行的操作。儘管Asp.net自身在展現層提供了Session(會話)對象,而ABP提供IAbpSession介面來獲取當前用戶和 ...
  • 文檔目錄 本節內容: 什麼時依賴註入 傳統方式的問題 解決方案 構造器註入模式 屬性註入模式 依賴註入框架 ABP 依賴註入基礎 註冊依賴 約定註入 輔助介面 自定義/直接 註冊 使用IocManager 使用Castle Windsor API 解析 構造器和屬性註入 IIocResolver 和 ...
  • 第一次在項目中遇到遠程訪問postgresql資料庫的,當時經常會出現連接資料庫的錯誤,連接字元串出現亂碼現象 解決方案 在配置文件中添加連接字元串 後臺代碼 最後連接成功 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...