反映 Refection
.NET提供的類別來實作反映
.NET提供了非常非常多讀取中繼資料的類別,大多數都在System.Reflection命名空間底下,這些類別可以動態載入程式集、呼叫模組、型別、方法、欄位等。
如上一篇所說的,程式集包含很多模組,模組包含很多型別,型別包含很多欄位和方法,所以為了讓讀者能了解,將包含的內容實體化,我們從最常用的型別開始往下分析。
先建立要被分析的特性(Attribute)與類別
//[AttributeUsage(AttributeTargets.Class)] 說明此Attribute是使用在class上面
[AttributeUsage(AttributeTargets.Class)]
public class ShowAttribute : Attribute
{
private string Message { get; set; }
public ShowAttribute(string message)
{
this.Message = message;
}
public void PrintMessage()
{
Console.WriteLine(Message);
}
}
[ShowAttribute("hi")]
public class AnalyzedClass
{
public string _stringField;
public int _intField;
public string MyProperty1 { get; set; }
public string MyProperty2 { get; set; }
public void Method()
{
Console.WriteLine("I'm Method");
}
public string ReturnValueMethod(string message)
{
return message;
}
}
開始分析逐一分析
分析流程:
型別→成員→方法→方法參數→屬性→特性
static void Main(string[] args)
{
AnalyzedClass ac = new AnalyzedClass();
Type type = ac.GetType();
// 分析Type
AnalyzeType(type);
// 分析成員
AnalyzeFieldInfo(type.GetFields());
//分析方法
AnalyzeMethodInfo(type.GetMethods());
//分析方法參數
foreach (var method in type.GetMethods())
{
AnalyzeMethodParameterInfo(method.GetParameters());
}
//分析屬性
AnalyzeProperyInfo(type.GetProperties());
//分析特性
AnalyzeAttributeInfo(type);
}
// 分析Type
private static void AnalyzeType(Type type)
{
// 型別名稱
Console.WriteLine("型別名稱: " + type.Name);
// output: AnalyzedClass
// 型別種類
Console.WriteLine("型別種類: " + type.Attributes);
// output: AutoLayout, AnsiClass, Class, public, BeforeFieldInit
// 型別的GUID
Console.WriteLine("型別的GUID: " + type.GUID);
// output:be2ebf30-5119..........
}
//分析成員
private static void AnalyzeFieldInfo(FieldInfo[] fields)
{
foreach (var field in fields)
{
// 成員名稱
Console.WriteLine("成員名稱: " + field.Name);
// output: _stringField 與 _intField
// 成員種類
Console.WriteLine("成員種類: " + field.Attributes);
// output: public 與 public
// 成員型別
Console.WriteLine("成員型別: " + field.FieldType);
// output: System.String 與 System.Int32
}
}
//分析方法
private static void AnalyzeMethodInfo(MethodInfo[] methods)
{
foreach (var method in methods)
{
// 方法名稱
Console.WriteLine("方法名稱: " + method.Name);
// output: Method 與 ReturnValueMethod
// 方法類別
Console.WriteLine("方法類別: " + method.Attributes);
// output: PrivateScope, Public, HideBySig
// 與 PrivateScope, Public, HideBySig
// 實際上output : 還有很多沒列出來,例如get,set 的 property方法
// 與物件的方法,例如GetType,ToString,Equals....等。
// 這些方法都會被分析出來
}
}
//分析方法參數
private static void AnalyzeMethodParameterInfo(ParameterInfo[] parameters)
{
foreach (var parameter in parameters)
{
// 參數名稱
Console.WriteLine("參數名稱: " + parameter.Name);
// output: message
// 參數種類
Console.WriteLine("參數種類: " + parameter.Attributes);
// output: None
// 參數型別
Console.WriteLine("參數型別: " + parameter.ParameterType);
// output: System.String
}
}
//分析屬性
private static void AnalyzeProperyInfo(PropertyInfo[] properites)
{
foreach (var properiy in properites)
{
// 屬性名稱
Console.WriteLine("屬性名稱: " + properiy.Name);
// output : MyProperty1 與 MyProperty2
// 屬性型別
Console.WriteLine("屬性型別: " + properiy.PropertyType);
// output : System.String 與 System.String
// 屬性種類
Console.WriteLine("屬性種類: " + properiy.Attributes);
// output : None 與 None
//是否可讀
Console.WriteLine("是否可讀: " + properiy.CanRead);
// output : true 與 true
//是否可寫
Console.WriteLine("是否可寫: " + properiy.CanWrite);
// output : true 與 true
}
}
//分析特性
private static void AnalyzeAttributeInfo(Type type)
{
// 取得屬性類別
ShowAttribute attr = Attribute.GetCustomAttribute(type, typeof(ShowAttribute)) as ShowAttribute;
attr.PrintMessage(); // output : hi
}
.NET提供的Reflection類別實在太多了,所以大概懂Type有什麼常用的類別就差不多了,到時需要再查MSDN。
上面程式碼分析了那麼多類別,接下就可以取用該類別,做一些事情,例如取用PropertyInfo 給Property值的方法:
AnalyzedClass ac = new AnalyzedClass();
// 先取得Type
Type type = ac.GetType();
// 取得Properies
PropertyInfo[] properties = type.GetProperties();
// 遍歷到我要設定的property
foreach (PropertyInfo property in properties)
{
// Set Value
switch (property.Name)
{
case "MyProperty1":
property.SetValue(ac, "Set Hello");
break;
case "MyProperty2":
property.SetValue(ac, "I'm Fine");
break;
}
}
// 此時ac就可以取用
Console.WriteLine("1 : " + ac.MyProperty1); // output : 1 : Set Hello
Console.WriteLine("2 : " + ac.MyProperty2); // output : 2 : I'm Fine
// 或者也可以用Reflection的方式取值
// 取得內容同上
foreach (PropertyInfo property in properties)
{
Console.WriteLine("Value : " + property.GetValue(ac));
}
.NET提供了這麼多實現反映機制的類別,程式師能夠很方便讀取中繼資料,動態建立物件的功能,了解Reflection的基本原理,寫底層的程式碼時,能夠提供很大的幫助。
一天一分享,身體好健康。
該追究的不是過去的原因,而是現在的目的。