在開發程式的過程中,常常會想要更加靈活的寫法,而這時映射(Reflection)可以大力的幫助到你, Reflection 允許我們的程式在執行時再去檢查和操作型別資訊,這對於如果你想要建立動態、可擴展的程式來說非常方便。接下來,我將介紹一些Reflection的基本用法並包含程式碼Code,以便幫助你更好的掌握這項技術。
第一步,我們需要引入Reflection所需的命名空間:
using System;
using System.Reflection;
接下來,建立一個MyClass
class MyClass
{
public int MyProperty { get; set; }
public void MyMethod()
{
// 輸出一段簡單的文字
Console.WriteLine("Hello, World!");
}
}
internal class Program
{
static void Main(string[] args)
{
// 獲取類別型別資訊
Type type = typeof(MyClass);
Console.WriteLine("Class Name: " + type.Name);
// 列出所有屬性
foreach (var property in type.GetProperties())
{
Console.WriteLine("Property: " + property.Name);
}
// 列出所有方法
foreach (var method in type.GetMethods())
{
Console.WriteLine("Method: " + method.Name);
}
// 暫停
Console.ReadLine();
}
}
執行結果如下:
動態建立類型並叫用其方法
假設我們想要創建一個 MyClass 的實體,但不直接使用 new 關鍵字。可以使用 Activator.CreateInstance 方法:
Type type = typeof(MyClass);
// 動態建立 MyClass 的實體
object instance = Activator.CreateInstance(type);
// 使用 GetMethod 獲取名為 MyMethod 的方法
MethodInfo methodInfo = type.GetMethod(“MyMethod”);
// 使用 Invoke 方法來呼叫 MyMethod
methodInfo.Invoke(instance, null);
執行結果如下:
在這段程式碼中,我們動態建立了 MyClass 的一個實體,並使用Reflection 呼叫了 MyMethod 方法。值得注意的是,如果MyClass擁有建構式,在Activator.CreateInstance時會一併呼叫其建構式。
修改屬性
Reflection也可以用來修改物件的屬性:
PropertyInfo propertyInfo = type.GetProperty(“MyProperty”);
propertyInfo.SetValue(instance, 42);
int propertyValue = (int)propertyInfo.GetValue(instance);
Console.WriteLine(“Property Value: “ + propertyValue);
執行結果如下:
透過這種方式,我們可以在不直接引用類別的情況下操作其屬性,這在動態程式設計時常常使用到。
呼叫私有成員
有些情況下,我們可能會需要呼叫私有類別的成員。雖然並不常這樣使用但 Reflection其實能做到這一點:
class MyClass
{
//私有方法
private void PrivateMethod()
{
Console.WriteLine("我是一個私有的方法。");
}
}
// BindingFlags.NonPublic 表示搜尋私有(private)的成員
// BindingFlags.Instance 表示搜尋實例成員(非靜態成員)
MethodInfo privateMethod = type.GetMethod(“PrivateMethod”, BindingFlags.NonPublic | BindingFlags.Instance);
privateMethod.Invoke(instance, null);
執行結果如下:
通過 BindingFlags,我們可以去指定私有方法。但必須特別注意,請減少使用這種做法,因為這麼做可能違反了物件導向程式設計的封裝原則,且也可能違背了當初程式開發人員所設計的邏輯。
使用時的注意事項
雖然Reflection很方便,但在使用時也要注意以下幾點:
- 性能:Reflection可能會比直接呼叫來的慢,在一些需要頻繁使用的情境下,還是要考慮Reflection的必要性。
- 安全性:通過Reflection訪問私有的屬性、方法可能會導致問題。
- 可維護性:當過度使用Reflection時,有可能導致程式變得難以理解和維護。
- 躲避編譯器檢查:在平時直接呼叫方法如果有錯,在編譯時就可以發現錯誤,但使用Reflection時,往往需要你在執行當下才可以發現錯誤。
結論
Reflection是 C# 提供的非常有用的工具,能夠使我們靈活的去撰寫程式碼,Reflection的各種動態地呼叫方法、建立物件等操作讓初次接觸的我完全沉迷於其中,但在使用時真的不得不謹慎,由於繞過了編譯時的型別檢查和安全檢查,除了確保程式的效能和安全性,還得考慮程式的可讀性與可維護性。希望這篇文章有幫助到你,謝謝
參考資料:
https://learn.microsoft.com/zh-tw/dotnet/csharp/advanced-topics/reflection-and-attributes/