天天看點

面向對象——反射

使用命名空間:System.Refection。

作用:可以檢視編譯好的類庫的内容。

反射的三種用法:1、檢視中繼資料。2、動态建立對象。3、動态調用方法。

反射的用途:

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

   (2)使用Module了解包含子產品的程式集以及子產品中的類等,還可以擷取在子產品上定義的所有全局方法或其他特定的非全局方法。

   (3)使用ConstructorInfo了解構造函數的名稱、參數、通路修飾符(如pulic 或private)和實作詳細資訊(如abstract或virtual)等。

   (4)使用MethodInfo了解方法的名稱、傳回類型、參數、通路修飾符(如pulic 或private)和實作詳細資訊(如abstract或virtual)等。

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

   (6)使用EventInfo了解事件的名稱、事件處理程式資料類型、自定義屬性、聲明類型和反射類型等,添加或移除事件處理程式。

   (7)使用PropertyInfo了解屬性的名稱、資料類型、聲明類型、反射類型和隻讀或可寫狀态等,擷取或設定屬性值。

   (8)使用ParameterInfo了解參數的名稱、資料類型、是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。

反射用到的命名空間:

   System.Reflection

   System.Type

   System.Reflection.Assembly

反射用到的主要類:

   System.Type 類--通過這個類可以通路任何給定資料類型的資訊。

   System.Reflection.Assembly類--它可以用于通路給定程式集的資訊,或者把這個程式集加載到程式中。

System.Type類:

   System.Type 類對于反射起着核心的作用。但它是一個抽象的基類,Type有與每種資料類型對應的派生類,我們使用這個派生類的對象的方法、字段、屬性來查找有關該類型的所有資訊。

   擷取給定類型的Type引用有3種常用方式:

   ●使用 C# typeof 運算符。

       Type t = typeof(string);

   ●使用對象GetType()方法。

       string s = "grayworm";

       Type t = s.GetType();

   ●還可以調用Type類的靜态方法GetType()。

       Type t = Type.GetType("System.String");

   上面這三類代碼都是擷取string類型的Type,在取出string類型的Type引用t後,我們就可以通過t來探測string類型的結構了。

           string n = "grayworm";

           Type t = n.GetType();

           foreach (MemberInfo mi in t.GetMembers())

           {

               Console.WriteLine("{0}/t{1}",mi.MemberType,mi.Name);

           }

   Type類的屬性:

       Name 資料類型名

       FullName 資料類型的完全限定名(包括命名空間名)

       Namespace 定義資料類型的命名空間名

       IsAbstract 訓示該類型是否是抽象類型

       IsArray   訓示該類型是否是數組

       IsClass   訓示該類型是否是類

       IsEnum   訓示該類型是否是枚舉

       IsInterface    訓示該類型是否是接口

       IsPublic 訓示該類型是否是公有的

       IsSealed 訓示該類型是否是密封類

       IsValueType 訓示該類型是否是值類型

   Type類的方法:

       GetConstructor(), GetConstructors():傳回ConstructorInfo類型,用于取得該類的構造函數的資訊

     GetEvent(), GetEvents():傳回EventInfo類型,用于取得該類的事件的資訊

     GetField(), GetFields():傳回FieldInfo類型,用于取得該類的字段(成員變量)的資訊

     GetInterface(), GetInterfaces():傳回InterfaceInfo類型,用于取得該類實作的接口的資訊

     GetMember(), GetMembers():傳回MemberInfo類型,用于取得該類的所有成員的資訊

     GetMethod(), GetMethods():傳回MethodInfo類型,用于取得該類的方法的資訊

     GetProperty(), GetProperties():傳回PropertyInfo類型,用于取得該類的屬性的資訊

   可以調用這些成員,其方式是調用Type的InvokeMember()方法,或者調用MethodInfo, PropertyInfo和其他類的Invoke()方法。

   檢視類中的構造方法:

       NewClassw nc = new NewClassw();

       Type t = nc.GetType();

       ConstructorInfo[] ci = t.GetConstructors();    //擷取類的所有構造函數

      foreach (ConstructorInfo c in ci) //周遊每一個構造函數

       {

           ParameterInfo[] ps = c.GetParameters();    //取出每個構造函數的所有參數

           foreach (ParameterInfo pi in ps)   //周遊并列印所該構造函數的所有參數

               Console.Write(pi.ParameterType.ToString()+" "+pi.Name+",");

           Console.WriteLine();

       }

   用構造函數動态生成對象:

       Type t = typeof(NewClassw);

       Type[] pt = new Type[2];

       pt[0] = typeof(string);

       pt[1] = typeof(string);

       //根據參數類型擷取構造函數

       ConstructorInfo ci = t.GetConstructor(pt);

       //構造Object數組,作為構造函數的輸入參數

       object[] obj = new object[2]{"grayworm","hi.baidu.com/grayworm"};  

       //調用構造函數生成對象

       object o = ci.Invoke(obj);    

       //調用生成的對象的方法測試是否對象生成成功

       //((NewClassw)o).show();    

   用Activator生成對象:

       //構造函數的參數

       object[] obj = new object[2] { "grayworm", "hi.baidu.com/grayworm" };  

       //用Activator的CreateInstance靜态方法,生成新對象

       object o = Activator.CreateInstance(t,"grayworm","hi.baidu.com/grayworm");

       //((NewClassw)o).show();

   檢視類中的屬性:

       PropertyInfo[] pis = t.GetProperties();

       foreach(PropertyInfo pi in pis)

           Console.WriteLine(pi.Name);

       }  

   檢視類中的public方法:

       MethodInfo[] mis = t.GetMethods();

       foreach (MethodInfo mi in mis)

           Console.WriteLine(mi.ReturnType+" "+mi.Name);

   檢視類中的public字段

       FieldInfo[] fis = t.GetFields();

       foreach (FieldInfo fi in fis)

           Console.WriteLine(fi.Name);

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

       object obj = Activator.CreateInstance(t);

       //取得ID字段

       FieldInfo fi = t.GetField("ID");

       //給ID字段指派

       fi.SetValue(obj, "k001");

       //取得MyName屬性

       PropertyInfo pi1 = t.GetProperty("MyName");

       //給MyName屬性指派

       pi1.SetValue(obj, "grayworm", null);

       PropertyInfo pi2 = t.GetProperty("MyInfo");

       pi2.SetValue(obj, "hi.baidu.com/grayworm", null);

       //取得show方法

       MethodInfo mi = t.GetMethod("show");

       //調用show方法

       mi.Invoke(obj, null);

System.Reflection.Assembly類

    Assembly類可以獲得程式集的資訊,也可以動态的加載程式集,以及在程式集中查找類型資訊,并建立該類型的執行個體。

   使用Assembly類可以降低程式集之間的耦合,有利于軟體結構的合理化。

   通過程式集名稱傳回Assembly對象

       Assembly ass = Assembly.Load("ClassLibrary831");

   通過DLL檔案名稱傳回Assembly對象

       Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");

   通過Assembly擷取程式集中類

       Type t = ass.GetType("ClassLibrary831.NewClass");   //參數必須是類的全名

   通過Assembly擷取程式集中所有的類

       Type[] t = ass.GetTypes();

   //通過程式集的名稱反射

   Assembly ass = Assembly.Load("ClassLibrary831");

   Type t = ass.GetType("ClassLibrary831.NewClass");

   object o = Activator.CreateInstance(t, "grayworm", "http://hi.baidu.com/grayworm");

   MethodInfo mi = t.GetMethod("show");

   mi.Invoke(o, null);

  //通過DLL檔案全名反射其中的所有類型

   Assembly assembly = Assembly.LoadFrom("xxx.dll的路徑");

   Type[] aa = a.GetTypes();

foreach(Type t in aa)

   {

       if(t.FullName == "a.b.c")

           object o = Activator.CreateInstance(t);

   }

檢視類的屬性方法和字段

private void button1_Click(object sender, EventArgs e)

{

           Type type = typeof(Button);

           MethodInfo[] infos = type.GetMethods();//檢視方法

           foreach (MethodInfo info in infos)

               listBox1.Items.Add(info.Name);

           PropertyInfo[] propInfos = type.GetProperties();//檢視屬性

           foreach (PropertyInfo info in propInfos)

  FieldInfo[] fieldInfo = type.GetFields(BindingFlags.NonPublic);//搜尋非公有字段

  foreach (FieldInfo i in fieldInfo)

  {

   listBox1.Items.Add(i.Name);

}

動态建立對象

注意:命名空間和程式集名稱

面向對象——反射

namespace SelectClass.Model

   public class UserInfo

       public string  Name { get; set; }

       public int Age { get; set; }

       public bool Sex { get; set; }

}

private void button1_Click(object sender, EventArgs e)

 {

     Assembly am = Assembly.Load("SelectClass.Model");//不用加DLL

     //Assembly am=Assembly.LoadFrom("SelectClass.Model.dll");

     UserInfo info = am.CreateInstance("SelectClass.Model.UserInfo") as UserInfo;

     if (info != null)

     {

          MessageBox.Show("動态建立成功!");

     }

  }

動态調用方法

   private void button1_Click(object sender, EventArgs e)

           Type ty = typeof(Form1);

           MethodInfo info = ty.GetMethod("Do", BindingFlags.Instance | BindingFlags.NonPublic);

           info.Invoke(this, null);

       private void Do()

           MessageBox.Show("aa");