天天看點

C#反射屬性例子

程式集包含子產品,而子產品包含類型,類型又包含成員。反射則提供了封裝程式集、子產品和類型的對象。您可以使用反射動态地建立類型的執行個體,将類型綁定到現有對象,或從現有對象中擷取類型。然後,可以調用類型的方法或通路其字段和屬性。反射通常具有以下用途:

使用 Assembly 定義和加載程式集,加載在程式集清單中列出的子產品,以及從此程式集中查找類型并建立該類型的執行個體。

使用 Module 了解如下的類似資訊:包含子產品的程式集以及子產品中的類等。您還可以擷取在子產品上定義的所有全局方法或其他特定的非全局方法。

使用 ConstructorInfo 了解以下資訊:構造函數的名稱、參數、通路修飾符(如 public 或 private)和實作詳細資訊(如 abstract 或 virtual)等。使用 Type 的 GetConstructors 或 GetConstructor 方法來調用特定的構造函數。

使用 MethodInfo 了解以下資訊:方法的名稱、傳回類型、參數、通路修飾符(如 public 或 private)和實作詳細資訊(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法來調用特定的方法。

使用 FieldInfo 了解以下資訊:字段的名稱、通路修飾符(如 public 或 private)和實作詳細資訊(如 static)等;并擷取或設定字段值。

使用 EventInfo 來了解如下的類似資訊:事件的名稱、事件處理程式資料類型、自定義屬性、聲明類型和反射類型等;并添加或移除事件處理程式。

使用 PropertyInfo 來了解如下的類似資訊:屬性的名稱、資料類型、聲明類型、反射類型和隻讀或可寫狀态等;并擷取或設定屬性值。

使用 ParameterInfo 來了解如下的類似資訊:參數的名稱、資料類型、參數是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。

當您在一個應用程式域的僅反射上下文中工作時,請使用 CustomAttributeData 來了解有關自定義屬性的資訊。使用 CustomAttributeData,您不必建立屬性的執行個體就可以檢查它們。[FROM:MSDN]

通過一個示例來簡要說明:

using System;

using System.Reflection;

namespace testReflection

{

    public delegate void TestDelegate(string info);

    class Program

    {

        static void Main(string[] args)

        {

             //從Dll中加載

             //Assembly ass = Assembly.LoadFile(@"TestReflect.dll");

             //Type myType = ass.GetType("testReflection.Person");

             //object aPerson = ass.CreateInstance("Person");

             //取得類型

            Type myType = Type.GetType ("testReflection.Person");

             //構造函數要用到的參數

            object [] constuctParms = new object[] { "Brad Pitt" };

            //建立執行個體

            //object TestName = Assembly.GetAssembly(myType).CreateInstance("Person");

            object aPerson = Activator.CreateInstance (myType, constuctParms);

             //使用MethodInfo 和Invoke 調用方法

            MethodInfo displayInfoMethod = myType.GetMethod ("DisplayInfo");

            displayInfoMethod .Invoke(aPerson, new object[] { "Using Invoke to call Method DisplayInfo()" });

            //使用InvokeMember 調用方法

            //調用方法的一些标志位

             BindingFlags flag = BindingFlags .InvokeMethod | BindingFlags.Public | BindingFlags.Instance;

            myType.InvokeMember("DisplayInfo", flag, null, aPerson, new object[] { "Using InvokeMethod to call DisplayInfo()" });

             //如果方法有傳回值

             string name = (string)myType.InvokeMember("getName" , flag, null , aPerson, null );

            System.Console.WriteLine( "call getName(), return: " + name );

            //設定屬性值

            myType.InvokeMember("Age" , BindingFlags.SetProperty, null, aPerson, new object[] { 30 });

            //得到屬性值

             int age = (int)myType.InvokeMember( "Age", BindingFlags.GetProperty, null, aPerson, null);

            System.Console .WriteLine("Get the property of Age : " + Convert.ToString(age));

             //設定字段值

            myType.InvokeMember ("Name", BindingFlags.SetField , null, aPerson , new object[] { "Michal Jodn" });

             //擷取字段值

            string fname = ( string)myType.InvokeMember("Name", BindingFlags.GetField, null , aPerson, null );

            System.Console.WriteLine("Get the Field Value of Name : " + fname);

            myType.InvokeMember("DisplayName", flag, null, aPerson, null);

            //獲得方法集

             MethodInfo[] methods = myType.GetMethods();

            foreach (MethodInfo m in methods) {

                System.Console.WriteLine(m.Name);

            }

            //同樣還有:GetFiedls()、GetProperties()、GetEvents()等方法

            //使用Delegate

            //此方法是靜态的,是以必須提供委托類型。

            TestDelegate dg = (TestDelegate)Delegate.CreateDelegate( typeof(testReflection.TestDelegate), aPerson, "DisplayInfo");

            dg ("Test Delegate by call DisplayInfo()");

            //獲得解決方案的所有Assembly

            Assembly[] AX = AppDomain.CurrentDomain.GetAssemblies();

            //周遊顯示每個Assembly的名字

            foreach (object var in AX ) {

                Console.WriteLine ("Assembly的名字:"+var.ToString());               

            }

             //使用一個已知的Assembly名稱,來建立一個Assembly

             //通過CodeBase屬性顯示最初指定的程式集的位置

            Console.WriteLine ("最初指定的程式集TestReflection的位置:" + Assembly.Load("TestReflection").CodeBase);

            System.Console.ReadLine();

         }

    }  

    public class Person

    {

        public string Name;

        private int _Age;

        public int Age

        {

            get

            {

                 return _Age;

             }

            set

            {

                _Age = value;

            }

        }

        public Person (string Name)

         {

            this.Name = Name;

        }

        public void DisplayInfo(string info)

        {

            System.Console.WriteLine(info );

            System.Console.WriteLine( "called sucessfully!");

        }

         public void DisplayName()

        {

            System .Console.WriteLine(Name);

        }

        public string getName()

        {

             return Name;

        }

    }

}

說明:

使用反射動态調用類成員,需要Type類的一個方法:InvokeMember。對該方法的聲明如下:

public object InvokeMember(

   string name,

   BindingFlags invokeAttr,

   Binder binder,

   object target,

   object[] args

);

參數

name

String,它包含要調用的構造函數、方法、屬性或字段成員的名稱。

- 或 -

空字元串 (""),表示調用預設成員。

invokeAttr

一個位屏蔽,由一個或多個指定搜尋執行方式的 BindingFlags 組成。通路可以是 BindingFlags 之一,如 Public、NonPublic、Private、InvokeMethod 和 GetField 等。不需要指定查找類型。如果省略查找類型,則将應用 BindingFlags.Public | BindingFlags.Instance。

binder

一個 Binder 對象,該對象定義一組屬性并啟用綁定,而綁定可能涉及選擇重載方法、強制參數類型和通過反射調用成員。

- 或 -

若為空引用(Visual Basic 中為 Nothing),則使用 DefaultBinder。

target

在其上調用指定成員的 Object。

args

包含傳遞給要調用的成員的參數的數組。

程式集包含子產品,而子產品包含類型,類型又包含成員。反射則提供了封裝程式集、子產品和類型的對象。您可以使用反射動态地建立類型的執行個體,将類型綁定到現有對象,或從現有對象中擷取類型。然後,可以調用類型的方法或通路其字段和屬性。反射通常具有以下用途:

使用 Assembly 定義和加載程式集,加載在程式集清單中列出的子產品,以及從此程式集中查找類型并建立該類型的執行個體。

使用 Module 了解如下的類似資訊:包含子產品的程式集以及子產品中的類等。您還可以擷取在子產品上定義的所有全局方法或其他特定的非全局方法。

使用 ConstructorInfo 了解以下資訊:構造函數的名稱、參數、通路修飾符(如 public 或 private)和實作詳細資訊(如 abstract 或 virtual)等。使用 Type 的 GetConstructors 或 GetConstructor 方法來調用特定的構造函數。

使用 MethodInfo 了解以下資訊:方法的名稱、傳回類型、參數、通路修飾符(如 public 或 private)和實作詳細資訊(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法來調用特定的方法。

使用 FieldInfo 了解以下資訊:字段的名稱、通路修飾符(如 public 或 private)和實作詳細資訊(如 static)等;并擷取或設定字段值。

使用 EventInfo 來了解如下的類似資訊:事件的名稱、事件處理程式資料類型、自定義屬性、聲明類型和反射類型等;并添加或移除事件處理程式。

使用 PropertyInfo 來了解如下的類似資訊:屬性的名稱、資料類型、聲明類型、反射類型和隻讀或可寫狀态等;并擷取或設定屬性值。

使用 ParameterInfo 來了解如下的類似資訊:參數的名稱、資料類型、參數是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。

當您在一個應用程式域的僅反射上下文中工作時,請使用 CustomAttributeData 來了解有關自定義屬性的資訊。使用 CustomAttributeData,您不必建立屬性的執行個體就可以檢查它們。[FROM:MSDN]

通過一個示例來簡要說明:

using System;

using System.Reflection;

namespace testReflection

{

    public delegate void TestDelegate(string info);

    class Program

    {

        static void Main(string[] args)

        {

             //從Dll中加載

             //Assembly ass = Assembly.LoadFile(@"TestReflect.dll");

             //Type myType = ass.GetType("testReflection.Person");

             //object aPerson = ass.CreateInstance("Person");

             //取得類型

            Type myType = Type.GetType ("testReflection.Person");

             //構造函數要用到的參數

            object [] constuctParms = new object[] { "Brad Pitt" };

            //建立執行個體

            //object TestName = Assembly.GetAssembly(myType).CreateInstance("Person");

            object aPerson = Activator.CreateInstance (myType, constuctParms);

             //使用MethodInfo 和Invoke 調用方法

            MethodInfo displayInfoMethod = myType.GetMethod ("DisplayInfo");

            displayInfoMethod .Invoke(aPerson, new object[] { "Using Invoke to call Method DisplayInfo()" });

            //使用InvokeMember 調用方法

            //調用方法的一些标志位

             BindingFlags flag = BindingFlags .InvokeMethod | BindingFlags.Public | BindingFlags.Instance;

            myType.InvokeMember("DisplayInfo", flag, null, aPerson, new object[] { "Using InvokeMethod to call DisplayInfo()" });

             //如果方法有傳回值

             string name = (string)myType.InvokeMember("getName" , flag, null , aPerson, null );

            System.Console.WriteLine( "call getName(), return: " + name );

            //設定屬性值

            myType.InvokeMember("Age" , BindingFlags.SetProperty, null, aPerson, new object[] { 30 });

            //得到屬性值

             int age = (int)myType.InvokeMember( "Age", BindingFlags.GetProperty, null, aPerson, null);

            System.Console .WriteLine("Get the property of Age : " + Convert.ToString(age));

             //設定字段值

            myType.InvokeMember ("Name", BindingFlags.SetField , null, aPerson , new object[] { "Michal Jodn" });

             //擷取字段值

            string fname = ( string)myType.InvokeMember("Name", BindingFlags.GetField, null , aPerson, null );

            System.Console.WriteLine("Get the Field Value of Name : " + fname);

            myType.InvokeMember("DisplayName", flag, null, aPerson, null);

            //獲得方法集

             MethodInfo[] methods = myType.GetMethods();

            foreach (MethodInfo m in methods) {

                System.Console.WriteLine(m.Name);

            }

            //同樣還有:GetFiedls()、GetProperties()、GetEvents()等方法

            //使用Delegate

            //此方法是靜态的,是以必須提供委托類型。

            TestDelegate dg = (TestDelegate)Delegate.CreateDelegate( typeof(testReflection.TestDelegate), aPerson, "DisplayInfo");

            dg ("Test Delegate by call DisplayInfo()");

            //獲得解決方案的所有Assembly

            Assembly[] AX = AppDomain.CurrentDomain.GetAssemblies();

            //周遊顯示每個Assembly的名字

            foreach (object var in AX ) {

                Console.WriteLine ("Assembly的名字:"+var.ToString());               

            }

             //使用一個已知的Assembly名稱,來建立一個Assembly

             //通過CodeBase屬性顯示最初指定的程式集的位置

            Console.WriteLine ("最初指定的程式集TestReflection的位置:" + Assembly.Load("TestReflection").CodeBase);

            System.Console.ReadLine();

         }

    }  

    public class Person

    {

        public string Name;

        private int _Age;

        public int Age

        {

            get

            {

                 return _Age;

             }

            set

            {

                _Age = value;

            }

        }

        public Person (string Name)

         {

            this.Name = Name;

        }

        public void DisplayInfo(string info)

        {

            System.Console.WriteLine(info );

            System.Console.WriteLine( "called sucessfully!");

        }

         public void DisplayName()

        {

            System .Console.WriteLine(Name);

        }

        public string getName()

        {

             return Name;

        }

    }

}

說明:

使用反射動态調用類成員,需要Type類的一個方法:InvokeMember。對該方法的聲明如下:

public object InvokeMember(

   string name,

   BindingFlags invokeAttr,

   Binder binder,

   object target,

   object[] args

);

參數

name

String,它包含要調用的構造函數、方法、屬性或字段成員的名稱。

- 或 -

空字元串 (""),表示調用預設成員。

invokeAttr

一個位屏蔽,由一個或多個指定搜尋執行方式的 BindingFlags 組成。通路可以是 BindingFlags 之一,如 Public、NonPublic、Private、InvokeMethod 和 GetField 等。不需要指定查找類型。如果省略查找類型,則将應用 BindingFlags.Public | BindingFlags.Instance。

binder

一個 Binder 對象,該對象定義一組屬性并啟用綁定,而綁定可能涉及選擇重載方法、強制參數類型和通過反射調用成員。

- 或 -

若為空引用(Visual Basic 中為 Nothing),則使用 DefaultBinder。

target

在其上調用指定成員的 Object。

args

包含傳遞給要調用的成員的參數的數組。

傳回值

表示被調用成員的傳回值的 Object。

下列 BindingFlags 篩選标志可用于定義包含在搜尋中的成員:

為了擷取傳回值,必須指定 BindingFlags.Instance 或 BindingFlags.Static。

指定 BindingFlags.Public 可在搜尋中包含公共成員。

指定 BindingFlags.NonPublic 可在搜尋中包含非公共成員(即私有成員和受保護的成員)。

指定 BindingFlags.FlattenHierarchy 可包含層次結構上的靜态成員。

下列 BindingFlags 修飾符标志可用于更改搜尋的執行方式:

BindingFlags.IgnoreCase,表示忽略 name 的大小寫。

BindingFlags.DeclaredOnly,僅搜尋 Type 上聲明的成員,而不搜尋被簡單繼承的成員。

可以使用下列 BindingFlags 調用标志表示要對成員采取的操作:

CreateInstance,表示調用構造函數。忽略 name。對其他調用标志無效。

InvokeMethod,表示調用方法,而不調用構造函數或類型初始值設定項。

對 SetField 或 SetProperty 無效。

GetField,表示擷取字段值。對 SetField 無效。

SetField,表示設定字段值。對 GetField 無效。

GetProperty,表示擷取屬性。對 SetProperty 無效。

SetProperty 表示設定屬性。對 GetProperty 無效。

傳回值

表示被調用成員的傳回值的 Object。

下列 BindingFlags 篩選标志可用于定義包含在搜尋中的成員:

為了擷取傳回值,必須指定 BindingFlags.Instance 或 BindingFlags.Static。

指定 BindingFlags.Public 可在搜尋中包含公共成員。

指定 BindingFlags.NonPublic 可在搜尋中包含非公共成員(即私有成員和受保護的成員)。

指定 BindingFlags.FlattenHierarchy 可包含層次結構上的靜态成員。

下列 BindingFlags 修飾符标志可用于更改搜尋的執行方式:

BindingFlags.IgnoreCase,表示忽略 name 的大小寫。

BindingFlags.DeclaredOnly,僅搜尋 Type 上聲明的成員,而不搜尋被簡單繼承的成員。

可以使用下列 BindingFlags 調用标志表示要對成員采取的操作:

CreateInstance,表示調用構造函數。忽略 name。對其他調用标志無效。

InvokeMethod,表示調用方法,而不調用構造函數或類型初始值設定項。

對 SetField 或 SetProperty 無效。

GetField,表示擷取字段值。對 SetField 無效。

SetField,表示設定字段值。對 GetField 無效。

GetProperty,表示擷取屬性。對 SetProperty 無效。

SetProperty 表示設定屬性。對 GetProperty 無效。

http://www.cnblogs.com/skyshenwei/archive/2010/01/19/1651893.html

繼續閱讀