C#反射基礎知識和實戰應用

來源:互聯網
上載者:User

標籤:style   blog   color   使用   檔案   os   

首先來說一下什麼是反射? 

反射提供了封裝程式集、模組和類型的對象(Type類型)

可以使用反射動態建立類型的執行個體,將類型綁定到現有對象,或從現有對象中擷取類型,然後,可以調用類型的方法或訪問其欄位和屬性 。

總之,有了反射,以前很多實現不了的功能都可以實現。

下面先來寫一個小例子,體驗一下反射是怎麼一回事:

開啟VS2010,建立一個控制台應用程式,在program.cs裡面寫代碼

首先引入命名空間:

using System.Reflection;

下如下代碼:

         PropertyInfo len = typeof(string).GetProperty("Length");         string s = "Hello,reflection!";         int length = (int)len.GetValue(s, null);         Console.WriteLine(length.ToString());

這裡通過反射擷取string的Length屬性,並通過調用PropertyInfo 的GetValues方法擷取屬性值,其中GetValues方法的原型如下:

public virtual object GetValue(object obj, object[] index);

第一個參數obj是擁有此屬性的類的執行個體,在這個例子中,為字串s,s擁有Length屬性。

第二個參數為索引值,微軟解釋如下:

Optional index values for indexed properties. This value should be null for non-indexed properties.

一般情況下用null,大家可以自己深入研究一下。

GetValues方法返回的是object類型,所以必須強制轉換類型。

 

下面通過反射來擷取string的一個方法,看看方法是如何通過反射得到的,代碼如下:

string s = "Hello,reflection!";MethodInfo method = typeof(string).GetMethod("Contains");bool result = (bool)method.Invoke(s, new object[] { "Hello" });Console.WriteLine(result);

其中,Invoke的方法定義如下:

public object Invoke(object obj, object[] parameters);

這個就很好理解了,第一個參數為擁有此方法的類的執行個體,還是為string執行個體s.

第二個參數就是一個object數組的參數。

這裡調用的是string中的Contains方法,判斷string中是否包含某個字串。

 

下面通過反射來執行個體化一個string對象,代碼如下:

     Type t = Type.GetType("System.String");         char[] para = new char[] { ‘H‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘ };         var o = Activator.CreateInstance(t, para);         Console.WriteLine(o);

這個跟擷取方法相似,唯一不同的就是string的構造方法參數是char[]數組,所以必須傳入符合的類型。這裡執行個體化了一個string,值為Hello。

 

看到這裡,你對反射已經有了初步的瞭解,下面開始進入實戰應用:

在解決方案上面點擊滑鼠右鍵,添加項目,選中類庫,輸入名稱,添加一個類庫。

在類庫中添加Custom類,代碼如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ReflectionDll{   public class Custom    {      public string Name { get; set; }      public string Address { get;set; }      public int Age { get; set; }      public DateTime BirthDay { get; set; }      public string GetInfo(string name = "",int age = 0)      {         if (name == "" && age == 0)         {            return "Custom Name: " + this.Name + ",Age: " + this.Age;         }         else         {            return "Custom Name: " + name + ",Age: " + age;         }      }   }}

這裡只聲明了幾個屬性和一個方法,供示範使用。寫好後編譯一下,在控制台項目裡面添加引用這個類庫(為了方便,否則每次編譯都要手動拷貝DLL到控制台項目下面),這樣VS會自動將產生的DLL拷貝到控制台debug目錄下,方便調用。下面開始使用反射來載入這個DLL,代碼如下:

        string path = Environment.CurrentDirectory + "\\ReflectionDll.dll";         Assembly assem = Assembly.LoadFile(path);         Type customType = assem.GetType("ReflectionDll.Custom");         var custom = Activator.CreateInstance(customType);

注意了,這裡首先要擷取DLL的實體路徑,所以上面是否添加引用是無所謂的。有了路徑後,通過Assembly的LoadFile方法載入DLL,再擷取類的Type,注意GetType方法裡面的參數必須為類的全稱,及命名空間 + 類名,否則無法找到。

最後一行,建立了一個類的執行個體,類型為object類型。

下面來擷取Custom的所有屬性,代碼如下:

 PropertyInfo[] propertys = customType.GetProperties();         Console.WriteLine("******************************");         foreach (PropertyInfo pro in propertys)         {            Console.WriteLine("PropertyName:" + pro.Name + "\n" +               "PropertyType:" + pro.PropertyType + "\n" +               "ClassName:" + pro.ReflectedType + "\n" +               "DLLName:" + pro.Module + "\n");         }         Console.WriteLine("******************************");

通過調用GetProperties方法擷取所有屬性,儲存到PropertyInfo[]數組中,然後遍曆數組輸出屬性值。

下面是各個屬性的含義:

Name                      屬性名稱

PropertyType          屬性資料類型

ReflectedType         所在的類的命名控制項 + 類名

Module                  所在的DLL檔案名稱

 

設定某個屬性的值,方法如下:

     PropertyInfo p = customType.GetProperty("Name");     p.SetValue(custom, "CustomName",null);

是不是很容易啊。。。

下面來說一下,調用類的方法,和一些屬性。代碼如下:

         MethodInfo _method = customType.GetMethod("GetInfo");         //顯示方法名稱         Console.WriteLine("Invoke method:" + _method.Name);         //顯示返回的資料類型         Console.WriteLine("Return type:" + _method.ReturnParameter);         ParameterInfo[] parameters =  _method.GetParameters();         foreach (ParameterInfo pa in parameters)         {            Console.WriteLine(pa.Name + pa.ParameterType + pa.Position + pa.Member);         }                  object[] paras = new object[] { "Jack",24 };         Console.WriteLine(_method.Invoke(custom, paras));
同屬性一樣,參數可以通過GetParameters()來擷取,擷取的參數資訊如下:

Name 參數名稱
ParameterType 參數資料類型
Position 參數的位置
Member 輸出所有參數

調用有參數的方法時,需要傳入參數,New一個object數組,將參數按順序寫入即可。


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.