反射技術在多數.NET程式中不會被使用,但是它的確是非常重要的技術,在很多應用程式中有著不可替代的作用。.Net的應用程式體系分為以下4個層次:程式集(Assembly)、模組(Module)、類型(Class)和類型成員(Member),反射技術可以在程式運行時擷取這4個層次的中繼資料資訊。只要掌握了反射技術實現的基本原理,就可以輕鬆解決各種形式的反射技術問題。
說明:應用程式定義域是程式集層次之上的更大的容器,一個應用程式定義域可以裝載多個程式集,本章暫不討論。
面試例題6:如何使用反射技術擷取指定類型中方法的完整資訊?
考點:反射技術的基本知識以及擷取Type對象的方式,瞭解System.Reflection命名空間下的類型。
出現頻率:★★★
解答
使用反射技術可以輕鬆擷取指定類型方法的完整資訊,首先擷取指定類型的Type對象,然後通過Type對象的成員擷取類型中方法的中繼資料資訊。本題定義了ClassA類,定義了2個方法,並重寫了ToString()方法,由於該類隱式繼承於System.Object類,所以該類還含有繼承於基類的多個方法。在主程式通過反射擷取方法資訊時,無法被Type對象擷取,這是因為MethodA()方法不是公用成員,在目錄下建立一個程式檔案,並命名為MethodRef.cs,編寫代碼如代碼7.6所示。
代碼7.6 反射擷取方法資訊:MethodRef.cs
{
CodeOp(this,true)
}">+展開
{
CodeOp(this)
}">-C#using System;
//匯入相應的命名空間
using System.Reflection;
class MethodRef
{
static void Main(string[] args)
{
//調用Type類的靜態方法GetType,並將Type對象引用返回給tp變數
Type tp = Type.GetType("ClassA", false, false);
//tp對象調用GetMethods方法,返回對象中所有公用方法數組,並賦值給ma數組
MethodInfo[] ma = tp.GetMethods();
Console.WriteLine("/n/t=================ClassA類所含的方法=================");
//遍曆ma數組中的所有MethodInfo類型子項
foreach (MethodInfo s in ma)
{
//依次輸出MethodInfo類型子項的屬性值
Console.WriteLine("/n/t【{0}方法】", s.Name);
Console.Write("方法所屬類名稱:【{0}】", s.DeclaringType);
Console.WriteLine("/t方法是否為建構函式:【{0}】", s.IsConstructor);
Console.Write("方法是否為public成員:【{0}】", s.IsPublic);
Console.WriteLine("/t方法是否為internal成員:【{0}】", s.IsAssembly);
Console.Write("方法是否為protected成員:【{0}】", s.IsFamily);
Console.WriteLine("/t方法是否為private成員:【{0}】", s.IsPrivate);
Console.Write("方法是否為泛型方法:【{0}】", s.IsGenericMethod);
Console.WriteLine("/t方法是否為靜態方法:【{0}】", s.IsStatic);
Console.Write("方法是否為virtual方法:【{0}】", s.IsVirtual);
Console.WriteLine("/t方法傳回型別為:【{0}】", s.ReturnType);
//調用s的GetParameters方法,返回ParameterInfo類型數組
//遍曆數組的ParameterInfo類型子項
foreach (ParameterInfo pms in s.GetParameters())
{
//輸出ParameterInfo類型子項的屬性
Console.WriteLine("/n/t------【{0}參數】------", pms.Name);
Console.Write("參數類型:【{0}】", pms.ParameterType);
Console.WriteLine("/t參數位置:【{0}】", pms.Position);
}
}
}
}
class ClassA
{
string _name;
//定義internal許可權的MethodA方法
internal string MethodA(string s)
{
_name = s;
return _name;
}
//定義public許可權的MethodB方法
public void MethodB(int i,string j)
{
Console.WriteLine("MethodA方法已調用,所傳遞參數為{0}和{1}",i,j);
}
//重寫ToString方法
public override string ToString()
{
return "ClassA類的對象";
}
}
在命令列下編譯MethodRef.cs,執行MethodRef程式,運行結果7.8所示。
本程式通過System.Type類的GetType()方法擷取ClassA類的Type對象tp,接著進行2層foreach語句嵌套,遍曆方法的詳細資料。當tp對象通過GetMethods()方法返回ma數組後,通過外層foreach語句遍曆並輸出該數組的MethodInfo類型子項屬性,即每個方法的屬性。在內層foreach語句結構中, ma數組子項調用GetParameters()方法返回的數組進行再次遍曆,即可輸出每個方法的參數詳細資料(每個參數對應一個 ParameterInfo類型對象)。