1. 程式人生 > >C# 反射(Reflection)

C# 反射(Reflection)

message console 反射 .html sys getmethod png source 文件

什麽是反射

發射是 .net framework 提供的一個幫助類庫,用於讀取和使用元數據。

用到的類:System.Reflection,System.Type。System.Type 類對於反射起著核心的作用。 當反射請求加載的類型時,公共語言運行時將為它創建一個 Type。 您可以使用 Type 對象的方法、字段、屬性和嵌套類來查找有關該類型的所有信息。

反射優缺點

優點:

  • 1、反射提高了程序的靈活性和擴展性。
  • 2、降低耦合性,提高自適應能力。
  • 3、它允許程序創建和控制任何類的對象,無需提前硬編碼目標類。

缺點:

  • 1、性能問題:使用反射基本上是一種解釋操作,用於字段和方法接入時要遠慢於直接代碼。因此反射機制主要應用在對靈活性和拓展性要求很高的系統框架上,普通程序不建議使用。
  • 2、使用反射會模糊程序內部邏輯;程序員希望在源代碼中看到程序的邏輯,反射卻繞過了源代碼的技術,因而會帶來維護的問題,反射代碼比相應的直接代碼更復雜。

反射的用途

  • 1、它允許在運行時查看特性(attribute)信息。
  • 2、它允許審查集合中的各種類型,以及實例化這些類型。
  • 3、它允許延遲綁定的方法和屬性(property)。
  • 4、它允許在運行時創建新類型,然後使用這些類型執行一些任務。
  • 5、MVC的路由就是反射做的。訪問的Global的時候,會加載一遍dll

查看元數據

1、獲取當前實例的 System.Type 的兩種方式

//使用對象 GetType()方法
Rectangle nc = new Rectangle(); Type type = nc.GetType(); //使用 C# typeof 運算符 Type type = typeof(Rectangle);

2、技術分享圖片查看類中的成員

MemberInfo[] minfos = type.GetMembers();
foreach (var i in minfos)
{
    Console.WriteLine("成員: {0}", i.Name);
}

3、查看類中的構造方法

ConstructorInfo[] ci = type.GetConstructors();
foreach (var i in ci) { Console.WriteLine("構造函數: {0}", i.Name); }

4、查看類中的屬性

PropertyInfo[] pis = type.GetProperties();
foreach (var i in pis)
{
    Console.WriteLine("屬性: {0}", i.Name);
}

5、查看類中的字段

FieldInfo[] fis = type.GetFields();
foreach (var i in fis)
{
    Console.WriteLine("字段: {0}", i.Name);
}

6、用反射生成對象,並調用屬性、方法和字段進行操作

object obj = Activator.CreateInstance(type);// 創建實例
FieldInfo fi = type.GetField("hight");// 取得length字段 
fi.SetValue(obj, 5);// 給ID字段賦值 
PropertyInfo pi1 = type.GetProperty("length");// 取得length屬性 
pi1.SetValue(obj, 10, null);// 給length屬性賦值
PropertyInfo pi2 = type.GetProperty("width");// 取得width屬性 
pi2.SetValue(obj, 20, null);// 給width屬性賦值 
MethodInfo mi = type.GetMethod("GetVolume");// 取得show方法 
mi.Invoke(obj, null);// 調用GetArea方法

7、查看類中的特性、

Object[] attributes = type.GetCustomAttributes(false);
foreach (var i in attributes)
{
    DeBugInfo dbi = i as DeBugInfo;
    if (null != dbi)
    {
        Console.WriteLine("Bug no: {0}, Message: {1}", dbi.BugNo, dbi.Message);
    }
}

8、完整代碼

技術分享圖片
using System;
using System.Reflection;
namespace ConsoleTest
{
    // 一個自定義特性 BugFix 被賦給類及其成員
    [AttributeUsage(AttributeTargets.Class |
    AttributeTargets.Constructor |
    AttributeTargets.Field |
    AttributeTargets.Method |
    AttributeTargets.Property,
    AllowMultiple = true)]

    public class DeBugInfo : System.Attribute
    {
        private int bugNo;
        public string message;

        public DeBugInfo(int bg)
        {
            this.bugNo = bg;
        }

        public int BugNo
        {
            get
            {
                return bugNo;
            }
        }
        public string Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }
    }
    /// <summary>
    /// 矩形
    /// </summary>
    [DeBugInfo(45, Message = "Return type mismatch")]
    [DeBugInfo(49, Message = "Unused variable")]
    public class Rectangle
    {
        public int hight = 0;
        public double length { get; set; }
        public double width { get; set; }
        public Rectangle()
        {
        }
        public Rectangle(double l, double w)
        {
            length = l;
            width = w;
        }
        // 計算面積
        [DeBugInfo(55, Message = "Return type mismatch")]
        public void GetArea()
        {
            Console.WriteLine("面積: {0}", length * width);
        }
        //計算體積
        [DeBugInfo(56)]
        public void GetVolume()
        {
            Console.WriteLine("體積: {0}", length * width * hight);
        }
    }

    class ExecuteRectangle
    {
        public static void Main12()
        {
            //使用對象GetType()方法
            //Rectangle nc = new Rectangle();
            //Type type = nc.GetType();
            
            //使用 C# typeof 運算符
            Type type = typeof(Rectangle);

            // 獲取 Rectangle 類的所有成員
            Console.WriteLine("\n遍歷 Rectangle 類的成員開始---------------");
            MemberInfo[] minfos = type.GetMembers();
            foreach (var i in minfos)
            {
                Console.WriteLine("成員: {0}", i.Name);
            }
            Console.WriteLine("-------------------結束-------------------");

            // 獲取 Rectangle 類的所有構造函數
            Console.WriteLine("\n遍歷 Rectangle 類的構造函數開始-----------");
            ConstructorInfo[] ci = type.GetConstructors();
            foreach (var i in ci)
            {
                Console.WriteLine("構造函數: {0}", i.Name);
            }
            Console.WriteLine("-------------------結束-------------------");

            // 獲取 Rectangle 類的所有屬性
            Console.WriteLine("\n遍歷 Rectangle 類的屬性開始---------------");
            PropertyInfo[] pis = type.GetProperties();
            foreach (var i in pis)
            {
                Console.WriteLine("屬性: {0}", i.Name);
            }
            Console.WriteLine("-------------------結束-------------------");

            // 獲取 Rectangle 類的所有public字段
            Console.WriteLine("\n遍歷 Rectangle 類的字段開始---------------");
            FieldInfo[] fis = type.GetFields();
            foreach (var i in fis)
            {
                Console.WriteLine("字段: {0}", i.Name);
            }
            Console.WriteLine("-------------------結束-------------------");

            //用反射生成對象,並調用屬性、方法和字段進行操作
            Console.WriteLine("\n用反射生成對象,並調用屬性、方法和字段進行操作");
            object obj = Activator.CreateInstance(type);// 創建實例
            FieldInfo fi = type.GetField("hight");// 取得length字段 
            fi.SetValue(obj, 5);// 給ID字段賦值 
            PropertyInfo pi1 = type.GetProperty("length");// 取得length屬性 
            pi1.SetValue(obj, 10, null);// 給length屬性賦值
            PropertyInfo pi2 = type.GetProperty("width");// 取得width屬性 
            pi2.SetValue(obj, 20, null);// 給width屬性賦值 
            MethodInfo mi = type.GetMethod("GetVolume");// 取得show方法 
            mi.Invoke(obj, null);// 調用GetArea方法
            Console.WriteLine("-------------------結束-------------------");

            // 遍歷 Rectangle 類的特性
            Console.WriteLine("\n遍歷 Rectangle 類的特性開始---------------");
            Object[] attributes = type.GetCustomAttributes(false);
            foreach (var i in attributes)
            {
                DeBugInfo dbi = i as DeBugInfo;
                if (null != dbi)
                {
                    Console.WriteLine("Bug no: {0}, Message: {1}", dbi.BugNo, dbi.Message);
                }
            }
            Console.WriteLine("-------------------結束-------------------");

            // 遍歷 Rectangle 類的方法上的特性(此處只遍歷)
            Console.WriteLine("\n遍歷 Rectangle 類的方法上的特性開始-------");
            MethodInfo[] m = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
            foreach (var i in m )
            {
                foreach (Attribute a in i.GetCustomAttributes(true))
                {
                    DeBugInfo dbi = a as DeBugInfo;
                    if (null != dbi)
                    {
                        Console.WriteLine("Bug no: {0}, for Method: {1}, Message: {2}", dbi.BugNo, i.Name, dbi.Message);
                    }
                }
            }
            Console.WriteLine("-------------------結束-------------------");

            Console.ReadLine();
        }
    }
}
反射的完整代碼

運行結果:

技術分享圖片

System.Reflection.Assembly類

Assembly類可以獲得程序集的信息,也可以動態的加載程序集,以及在程序集中查找類型信息,並創建該類型的實例。
使用Assembly類可以降低程序集之間的耦合,有利於軟件結構的合理化。

//通過程序集名稱返回Assembly對象
Assembly ass = Assembly.Load("ConsoleTest");

//通過DLL、EXE文件名稱返回Assembly對象
Assembly ass = Assembly.LoadFrom("ConsoleTest.exe");

//通過Assembly獲取程序集中類
Type t = ass.GetType("ConsoleTest.Rectangle");   //參數必須是類的全名

//通過Assembly獲取程序集中所有的類
Type[] types = ass.GetTypes();


相關文章:http://www.runoob.com/csharp/csharp-reflection.html

https://www.cnblogs.com/Kare/p/4601436.html

C# 反射(Reflection)