程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#反射機制,

C#反射機制,

編輯:C#入門知識

C#反射機制,


   最近項目上使用到到反射,找到以前保留的一份文檔,作者是李志偉,沒有找到他的博客地址,所以不知道出處在哪,抱歉!如果作者看到,請聯系我好注明出處。

   在這分享一下。

1.反射機制基礎類

(1)反射機制的功能與介紹

審查元數據並收集關於它的類型信息的能力稱為反射。元數據(編譯以後的最基本數據單元)就是一大堆的表,當編譯程序集或者模塊時,編譯器會創建一個類定義表,一個字段定義表,和一個方法定義表等。System.reflection命名空間包含的幾個類,允許用戶解析這些元數據表的代碼:

System.Reflection.Assembly:表示一個程序集。

System.Reflection.Module:在模塊上執行反射。

System.Type:表示各種類型。

System.Reflection.MethodBase:提供有關方法和構造函數的信息。

System.Reflection.MethodInfo:發現方法的屬性並提供對方法元數據的訪問。

System.Reflection.MemberInfo:獲取或訪問有關成員屬性。

System.Reflection.FieldInfo:發現字段屬性並提供對字段元數據的訪問權。

System.Reflection.PropertyInfo:發現或訪問屬性(Property)的屬性(Attribute)。

System.Reflection.EventInfo:發現事件的屬性並提供對事件元數據的訪問權。

System.Reflection.ConstructorInfo:發現或訪問類構造函數的屬性。

(2)反射層次模型圖

(3)Assembly類獲取程序及信息

    class Program

    {

        static void Main(string[] args)

        {

            Assembly assem = Assembly.Load("mscorlib");//加載系統程序集

            PrintInfo(assem);//輸出程序集相關信息

            assem = Assembly.LoadFrom(@"F:\System.Data.SQLite.dll");//或使用LoadFile()方法

            PrintInfo(assem);//輸出程序集相關信息

            assem = Assembly.GetExecutingAssembly();//獲取當前執行代碼的程序集

            PrintInfo(assem);//輸出程序集相關信息

            Console.Read();

        }

        //輸出程序集相關信息

        static void PrintInfo(Assembly assem)

        {

            Console.WriteLine("程序集全名:" + assem.FullName);

            Console.WriteLine("程序集的版本:" + assem.GetName().Version);

            Console.WriteLine("程序集初始位置:" + assem.CodeBase);

            Console.WriteLine("程序集位置:" + assem.Location);

            Console.WriteLine("程序集入口:" + assem.EntryPoint);

            Type[] types = assem.GetTypes();//得到該程序集裡所有的類型

            Console.WriteLine("程序集下包含的類型數:" + types.Length);

            //foreach (var item in types)

            //{

            //    Console.WriteLine("類:" + item.Name);//輸出類型名

            //}

            Console.WriteLine("============================\n");

        }

    }

(4)Module類獲取程序集模塊信息

    class Program

    {

        static void Main(string[] args)

        {

            Assembly assembly = Assembly.Load("mscorlib");//加載程序集

            Module module = assembly.GetModule("CommonLanguageRuntimeLibrary");//得到指定模塊

            Console.WriteLine("模塊名:"+module.Name);

            Type[] types = module.FindTypes(Module.FilterTypeName, "Assembly*");

            foreach (var item in types)

            {

                Console.WriteLine("類名:" + item.Name);//輸出類型名

            }

            Console.Read();

        }

    }

(5)Type類獲取類型的信息

    class Myclass

    {

        private int Id;

        public string Name;

        public void Method(int i) { }

    }

    class Program

    {

        static void Main(string[] args)

        {

            Type type = typeof(Myclass);

            Console.WriteLine("類型名:" + type.Name);

            Console.WriteLine("類全名:" + type.FullName);

            Console.WriteLine("命名空間名:" + type.Namespace);

            Console.WriteLine("程序集名:" + type.Assembly);

            Console.WriteLine("模塊名:" + type.Module);

            Console.WriteLine("基類名:" + type.BaseType);

            Console.WriteLine("是否類:" + type.IsClass);

            Console.WriteLine("類的公共成員:");

            MemberInfo[] memberInfos = type.GetMembers();//得到所有公共成員

            foreach (var item in memberInfos)

            {

                Console.WriteLine("成員類型:" + item.MemberType + "\t成員:" + item);

            }

            Console.Read();

        }

    }

(6)利用反射調用方法

    class Myclass

    {

        public Myclass()

        {

            Console.WriteLine("創建Myclass對象!");

        }

        public void Method(int i)

        {

            Console.WriteLine("輸出值:" + i);

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            Type t = typeof(Myclass);//得到類型

            object o = Activator.CreateInstance(t);//創建類型的實例

            Console.WriteLine("已創建Myclass對象:" + o);

            MethodInfo method = t.GetMethod("Method");//獲得實例的方法

            method.Invoke(o, new object[] { 100 });//調用方法

            Console.Read();

        }

    }

2.特性(Attribute)

(1)Attribute介紹

Attributes是一種新的描述信息,我們既可以使用attributes來定義設計信息(例如:幫助文件,文檔的URL),還可以用attributes定義運行時信息(例如,使XML中的元素與類的成員字段關聯起來)。我們也可以用attributes來創建一個“自描述”的組件。

(2)示例

    class Program

    {

        [Obsolete("已過時的方法!", true)]//把true改成false就可以編譯通過

        static void OldMethod() { }

        static void Main(string[] args)

        {

            OldMethod();//調用過時的方法

            Console.Read();

        }

}

在該實例中我們用到了“Obsolete”Attribute,它標記了一個不該再被使用的語言元素(這裡的元素為方法),該屬性的第一個參數是string類型,它解釋為什麼該元素被荒棄,以及我們該使用什麼元素來代替它。實際中,我們可以書寫任何其它文本來代替這段文本。第二個參數是告訴編譯器把依然使用這被標識的元素視為一種錯誤,這就意味著編譯器會因此而產生一個警告。

3.自定義特性

(1)自定義特性說明

自定義的Attribute類都派生於System.Attribute類。

(2)示例

    //自定義的Attribute類命名為XXXAttribute

    class HelpAttribute : Attribute

    {

        private String description;

        public HelpAttribute(String Descrition_in)

        {

            this.description = Descrition_in;

        }

        public String Description

        {

            get { return description; }

        }

    }

    class Program

    {

        [Help("自定義特性")]//使用是不需要寫“Attribute”後綴

        static void Main(string[] args)

        {

            Console.Read();

        }

}

注意:按慣例我們是用”Attribute“作為attribute類名的後綴,然而,當我們當我們把attribute綁定到某語言元素時,是不包含“Attribute“後綴的。編譯器首先在System.Attribute 的繼承類中查找該attribute,如果沒有找到,編譯器會把“Attribute“追加到該attribute的名字後面,然後查找它。

(3)AttributeUsage類的使用

AttributeUsage類是另一預定義類(Attribute類本身用System.AttributeUsage類來標記),它將幫助我們控制我們自定義Attribute類的用法,這就是,我們能為自定義的Attribute類定義Attributes屬性。它描述了一個自定義Attribute類能被怎樣使用。

AttributeUsage提供三個屬性,我們能將它們放置到我們的自定義Attribute類上。

AllowMultiple屬性:該值指示能否為一個程序元素指定多個指示屬性實例。

Inherited屬性:該值指示指示的屬性能否由派生類和重寫成員繼承。

ValidOn屬性:獲取一組值,這組值標識指示的屬性可應用到的程序元素。此屬性是AttributeTargets類型的枚舉,可取如下值:

使用示例:

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]

    class HelpAttribute : Attribute

    {

        private String description;

        public HelpAttribute(String Descrition_in)

        {

            this.description = Descrition_in;

        }

        public String Description

        {

            get { return description; }

        }

    }

    class Program

    {

        [Help("自定義特性")]

        static void Main(string[] args)

        {

            Console.Read();

        }

    }

(4)可選參數與命名參數

可選參數是Attribute類構造函數的參數。它是強制的,必須在每次在Attribute綁定至某語言元素時提供一個值。而另一方面,命名參數倒是真正的可選參數,不是在Attribute構造函數的參數。

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]

    class HelpAttribute : Attribute

    {

        private string _description;//可選參數

        public string _name;//命名參數

        public HelpAttribute(string description)

        {

            Console.WriteLine("HelpAttribute特性被創建!");

            this._description = description;

        }

        public string Description

        {

            get { return _description; }

        }

        public string Name

        {

            get { return _name; }

            set//命名參數,必須要有set方法

            {

                Console.WriteLine("屬性:" + value);

                _name = value;

            }

        }

    }

    class Program

    {

        [Help("自定義特性", Name = "李志偉")]//同時使用可選參數與命名參數

        static void Main(string[] args)

        {

            Console.Read();

        }

    }

(5)Attributes標識符

假設,我們想把HelpAttribute綁定到整個assembly(程序集)。第一個問題是我們要把HelpAttribute放在哪兒才能讓編譯器確定該Attribute是綁定至整個assembly呢?考慮另一種情況,我們想把Attribute綁定至一個方法的返回類型上,怎樣才能讓編譯器確定我們是把Attribute綁定至方法的返回類型上,而不是整個方法呢?

為了解決諸如此類的含糊問題,我們使用Attribute標識符,有了它的幫助,我們就可以確切地申明我們把attribute 綁定至哪一個語言元素。例如:[assembly: Help("類上的自定義特性", Name = "lizhiwei")]這個在HelpAttribute前的assembly標識符確切地告訴編譯器,該Attribute被綁定至整個assembly(程序集)。可能的標識符有:assembly、module、type、method、property、event、field、param、return。

(6)通過反射獲取Attributes

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]

    class HelpAttribute : Attribute

    {

        private string _description;//可選參數

        private string _name;//命名參數

        public HelpAttribute(string description)

        {

            Console.WriteLine("====HelpAttribute特性被創建!====");

            this._description = description;

        }

        public string Description

        {

            get { return _description; }

        }

        public string Name

        {

            get { return _name; }

            set//命名參數,必須要有set方法

            {

                Console.WriteLine("====屬性:" + value + "====");

                _name = value;

            }

        }

    }

    //使用了自定義特性的測試類

    [Help("類上的自定義特性", Name = "lizhiwei")]

    class TestClass

    {

        [Help("方法上的自定義特性", Name = "李志偉1")]

        [Help("方法上的自定義特性", Name = "李志偉2")]

        public void TestMethod()

        {

            Console.WriteLine("===========測試方法===========");

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            Type t = typeof(TestClass);

            //獲取類上的自定義特性

            object[] obis = t.GetCustomAttributes(typeof(HelpAttribute), false);

            HelpAttribute attribute = obis[0] as HelpAttribute;

            Console.WriteLine("\n" + attribute.Description + "--" + attribute.Name + "\n");

            //獲取方法上的自定義特性

            MethodInfo method = t.GetMethod("TestMethod");

            object[] methods = method.GetCustomAttributes(typeof(HelpAttribute), false);

            foreach (HelpAttribute help in methods)

            {

                Console.WriteLine("\n" + help.Description + "--" + help.Name + "\n");

            }

            Console.Read();

        }

    }


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved