天天看點

接觸C# 反射1、反射的概念詳解[1]3、一個利用反射擷取屬性值的較為詳細的例子

1、B超:大家體檢的時候大概都做過B超吧,B超可以透過肚皮探測到你内髒的生理情況。這是如何做到的呢?B超是B型超音波,它可以透過肚皮通過向你體内 發射B型超音波,當超音波遇到内髒壁的時候就會産生一定的“回音”反射,然後把“回音”進行處理就可以顯示出内髒的情況了(我不是醫生也不是聲學專家,不 知說得是否準确^_^)。

2、地球内部結構:地球的内部結構大體可以分為三層:地殼、地幔和地核。地殼是固體,地核是液體,地幔則是半液半固的結構(中學地理的内容,大家還記得 吧?)。如何在地球表面不用深入地球内部就知道其内部的構造呢?對,向地球發射“地震波”,“地震波”分兩種一種是“橫波”,另一種是“縱波”。“橫波” 隻能穿透固體,而“縱波”既可穿透固體又可以穿透液體。通過在地面對縱波和橫波的反回情況,我們就可以大體斷定地球内部的構造了。

大家注意到這兩個例子的共同特點,就是從一個對象的外部去了解對象内部的構造,而且都是利用了波的反射功能。在.NET中的反射也可以實作從對象的外部來了解對象(或程式集)内部結構的功能,哪怕你不知道這個對象(或程式集)是個什麼東西,另外.NET中的反射還可以運态建立出對象并執行它其中的方法。

反射是.NET中的重要機制,通過反射,可以在運作時獲得程式或程式集中每一個類型(包括類、結構、委托、接口和枚舉等)的成員和成員的資訊。有了反射,即可對每一個類型了如指掌。另外我還可以直接建立對象,即使這個對象的類型在編譯時還不知道。 

1.2 反射的用途

(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了解參數的名稱、資料類型、是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。

1.3 反射用到的命名空間

    System.Reflection

    System.Type

    System.Reflection.Assembly

2、反射用到的主要類

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

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

2.1  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類型的結構了。

1

2

3

4

5

6

<code>string</code> <code>n = </code><code>"grayworm"</code><code>;</code>

<code>Type t = n.GetType();</code>

<code>foreach</code> <code>(MemberInfo mi </code><code>in</code> <code>t.GetMembers())</code>

<code>{</code>

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

<code>}</code>

    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()方法。 

    檢視類中的構造方法:

7

8

9

10

11

12

<code>NewClassw nc = </code><code>new</code> <code>NewClassw();</code>

<code>Type t = nc.GetType();</code>

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

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

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

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

<code>    </code><code>{</code>

<code>Console.Write(pi.ParameterType.ToString()+</code><code>" "</code><code>+pi.Name+</code><code>","</code><code>);</code>

<code>    </code><code>}</code>

<code>    </code><code>Console.WriteLine();</code>

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

<code>Type t = </code><code>typeof</code><code>(NewClassw);</code>

<code>Type[] pt = </code><code>new</code> <code>Type[2];</code>

<code>pt[0] = </code><code>typeof</code><code>(</code><code>string</code><code>);</code>

<code>pt[1] = </code><code>typeof</code><code>(</code><code>string</code><code>);</code>

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

<code>ConstructorInfo ci = t.GetConstructor(pt);</code>

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

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

<code>//調用構造函數生成對象</code>

<code>object</code> <code>o = ci.Invoke(obj);   </code>

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

<code>//((NewClassw)o).show();  </code>

    用Activator生成對象:

<a></a>

    檢視類中的屬性:

<code>PropertyInfo[] pis = t.GetProperties();</code>

<code>foreach</code><code>(PropertyInfo pi </code><code>in</code> <code>pis)</code>

<code>    </code><code>Console.WriteLine(pi.Name);</code>

    檢視類中的public方法:

<code>MethodInfo[] mis = t.GetMethods();</code>

<code>foreach</code> <code>(MethodInfo mi </code><code>in</code> <code>mis)</code>

<code>    </code><code>Console.WriteLine(mi.ReturnType+</code><code>" "</code><code>+mi.Name);</code>

    檢視類中的public字段

<code>FieldInfo[] fis = t.GetFields();</code>

<code>foreach</code> <code>(FieldInfo fi </code><code>in</code> <code>fis)</code>

<code>    </code><code>Console.WriteLine(fi.Name);</code>

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

13

14

15

16

17

<code>object</code> <code>obj = Activator.CreateInstance(t);</code>

<code>//取得ID字段</code>

<code>FieldInfo fi = t.GetField(</code><code>"ID"</code><code>);</code>

<code>//給ID字段指派</code>

<code>fi.SetValue(obj, </code><code>"k001"</code><code>);</code>

<code>//取得MyName屬性</code>

<code>PropertyInfo pi1 = t.GetProperty(</code><code>"MyName"</code><code>);</code>

<code>//給MyName屬性指派</code>

<code>pi1.SetValue(obj, </code><code>"grayworm"</code><code>, </code><code>null</code><code>);</code>

<code>PropertyInfo pi2 = t.GetProperty(</code><code>"MyInfo"</code><code>);</code>

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

<code>//取得show方法</code>

<code>MethodInfo mi = t.GetMethod(</code><code>"show"</code><code>);</code>

<code>//調用show方法</code>

<code>mi.Invoke(obj, </code><code>null</code><code>);</code>

2.2 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();

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

<code>Assembly ass = Assembly.Load(</code><code>"ClassLibrary831"</code><code>);</code>

<code>Type t = ass.GetType(</code><code>"ClassLibrary831.NewClass"</code><code>);</code>

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

<code>mi.Invoke(o, </code><code>null</code><code>);</code>

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

<code>Assembly assembly = Assembly.LoadFrom(</code><code>"xxx.dll的路徑"</code><code>);</code>

<code>Type[] aa = a.GetTypes();</code>

<code>foreach</code><code>(Type t </code><code>in</code> <code>aa)</code>

<code>     </code><code>if</code><code>(t.FullName == </code><code>"a.b.c"</code><code>)</code>

<code>     </code><code>{</code>

<code>         </code><code>object</code> <code>o = Activator.CreateInstance(t);</code>

<code>     </code><code>}</code>

c# 如何通過反射擷取屬性值[2]。

<code>public</code> <code>class</code> <code>A</code>

<code>    </code><code>public</code> <code>int</code> <code>Property1 { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>static</code> <code>void</code> <code>Main(){</code>

<code>    </code><code>A aa = </code><code>new</code> <code>A();</code>

<code>    </code><code>Type type = aa.GetType();</code><code>//擷取類型</code>

<code>    </code><code>System.Reflection.PropertyInfo propertyInfo = type.GetProperty(</code><code>"Property1"</code><code>);</code>

<code>    </code><code>propertyInfo.SetValue(aa, 5, </code><code>null</code><code>);</code><code>//給對應屬性指派</code>

<code>    </code><code>int</code> <code>value = (</code><code>int</code><code>)propertyInfo.GetValue(aa, </code><code>null</code><code>);</code>

<code>    </code><code>Console.WriteLine(value );</code>

中等規模的類的反射方式擷取屬性值[3],這是一個控制台程式。具體代碼如下。

學生字典類(S0001):

 StudentDict 類1

學生字典類:(S0002):

 StudentDict 類2

主函數,Program主類:

 Program

3.3.1

18

<code>//定義類</code>

<code>public</code> <code>class</code> <code>MyClass</code>

<code>public</code> <code>int</code> <code>Property1 { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>static</code> <code>void</code> <code>Main()</code>

<code>MyClass tmp_Class = </code><code>new</code> <code>MyClass();</code>

<code>tmp_Class.Property1 = 2;</code>

<code>Type type = tmp_Class.GetType(); </code><code>//擷取類型</code>

<code>System.Reflection.PropertyInfo propertyInfo = type.GetProperty(</code><code>"Property1"</code><code>); </code><code>//擷取指定名稱的屬性</code>

<code>int</code> <code>value_Old = (</code><code>int</code><code>)propertyInfo.GetValue(tmp_Class, </code><code>null</code><code>); </code><code>//擷取屬性值</code>

<code>Console.WriteLine(value_Old);</code>

<code>propertyInfo.SetValue(tmp_Class, 5, </code><code>null</code><code>); </code><code>//給對應屬性指派</code>

<code>int</code> <code>value_New = (</code><code>int</code><code>)propertyInfo.GetValue(tmp_Class, </code><code>null</code><code>);</code>

<code>Console.WriteLine(value_New);</code>

3.3.2  利用反射擷取對象屬性值

<code>public</code> <code>static</code> <code>string</code> <code>GetObjectPropertyValue&lt;T&gt;(T t, </code><code>string</code> <code>propertyname)</code>

<code>     </code><code>Type type = </code><code>typeof</code><code>(T);</code>

<code>      </code><code>PropertyInfo property = type.GetProperty(propertyname);</code>

<code>      </code><code>if</code> <code>(property == </code><code>null</code><code>) </code><code>return</code> <code>string</code><code>.Empty;</code>

<code>      </code><code>object</code> <code>o = property.GetValue(t, </code><code>null</code><code>);</code>

<code>      </code><code>if</code> <code>(o == </code><code>null</code><code>) </code><code>return</code> <code>string</code><code>.Empty;</code>

<code>      </code><code>return</code> <code>o.ToString();</code>

參考博文

沒有整理與歸納的知識,一文不值!高度概括與梳理的知識,才是自己真正的知識與技能。 永遠不要讓自己的自由、好奇、充滿創造力的想法被現實的架構所束縛,讓創造力自由成長吧! 多花時間,關心他(她)人,正如别人所關心你的。理想的騰飛與實作,沒有别人的支援與幫助,是萬萬不能的。

    本文轉自wenglabs部落格園部落格,原文連結:http://www.cnblogs.com/arxive/p/5778034.html,如需轉載請自行聯系原作者