化妝培訓(xùn)網(wǎng)站模板百度網(wǎng)頁網(wǎng)址
📅 Day 20:反射與特性(Reflection & Attributes)
? 學(xué)習(xí)目標(biāo):
- 理解什么是 反射(Reflection) 及其作用;
- 掌握如何使用反射動態(tài)獲取類型信息、創(chuàng)建對象和調(diào)用方法;
- 理解 特性(Attributes) 是什么及其用途;
- 學(xué)會定義和使用自定義特性;
- 能夠結(jié)合反射與特性實(shí)現(xiàn)插件系統(tǒng)、序列化器或自動注冊功能;
- 編寫一個(gè)使用反射加載程序集并執(zhí)行方法的示例。
🧠 一、什么是反射(Reflection)?
反射(Reflection) 是 .NET 提供的一種機(jī)制,允許你在運(yùn)行時(shí)動態(tài)地分析、檢查和操作程序集中的類型(如類、接口、方法、屬性等)。
常見用途:
場景 | 示例 |
---|---|
自動測試工具 | 使用反射查找所有測試類和方法 |
序列化/反序列化 | 動態(tài)讀取對象屬性進(jìn)行 JSON 映射 |
插件系統(tǒng) | 動態(tài)加載 DLL 并調(diào)用其中的方法 |
依賴注入容器 | 根據(jù)類型自動解析構(gòu)造函數(shù)參數(shù) |
🔍 二、反射常用功能
獲取類型信息
Type type = typeof(string);
Console.WriteLine("類型名稱:" + type.FullName);
獲取對象的運(yùn)行時(shí)類型
object obj = "Hello";
Type runtimeType = obj.GetType();
創(chuàng)建對象實(shí)例
Type type = typeof(string);
object instance = Activator.CreateInstance(type);
注意:對于有參數(shù)的構(gòu)造函數(shù),需要傳遞參數(shù)數(shù)組。
獲取和調(diào)用方法
MethodInfo method = type.GetMethod("MethodName", new[] { typeof(int) });
method.Invoke(instance, new object[] { 42 });
獲取屬性和字段
PropertyInfo prop = type.GetProperty("Name");
prop.SetValue(instance, "張三");object value = prop.GetValue(instance);
?? 三、反射性能優(yōu)化建議
反射雖然強(qiáng)大,但性能較低。以下是一些優(yōu)化方式:
方法 | 說明 |
---|---|
Expression Trees | 構(gòu)建委托緩存以提高重復(fù)調(diào)用性能 |
Delegate.CreateDelegate | 將 MethodInfo 轉(zhuǎn)換為委托 |
緩存反射結(jié)果 | 避免重復(fù)調(diào)用 GetMethod / GetProperty |
🎯 四、什么是特性(Attribute)?
特性(Attribute) 是一種元數(shù)據(jù)機(jī)制,用于向代碼元素(如類、方法、屬性)附加額外的信息。
這些信息可以在編譯時(shí)或運(yùn)行時(shí)通過反射讀取。
🧩 五、內(nèi)置特性示例
特性 | 說明 |
---|---|
[Obsolete] | 標(biāo)記某個(gè)方法已過時(shí) |
[Serializable] | 表示該類可被序列化 |
[DllImport] | 用于調(diào)用非托管 DLL 函數(shù) |
[Conditional] | 控制方法是否在特定條件下編譯 |
示例:
[Obsolete("請使用 NewMethod 替代")]
public void OldMethod()
{// ...
}
🧱 六、自定義特性(Custom Attribute)
你可以定義自己的特性類,繼承 Attribute
:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class AuthorAttribute : Attribute
{public string Name { get; }public AuthorAttribute(string name){Name = name;}
}
然后應(yīng)用到類或方法上:
[Author("李四")]
public class MyService
{[Author("王五")]public void DoWork(){// ...}
}
🔍 七、通過反射讀取特性
Type type = typeof(MyService);// 獲取類上的特性
foreach (var attr in type.GetCustomAttributes(false))
{if (attr is AuthorAttribute author){Console.WriteLine($"類作者:{author.Name}");}
}// 獲取方法上的特性
MethodInfo method = type.GetMethod("DoWork");
foreach (var attr in method.GetCustomAttributes(true))
{if (attr is AuthorAttribute author){Console.WriteLine($"方法作者:{author.Name}");}
}
💪 實(shí)戰(zhàn)練習(xí):構(gòu)建一個(gè)基于特性和反射的插件系統(tǒng)
功能要求:
- 定義一個(gè)插件接口;
- 使用特性標(biāo)記插件類;
- 使用反射掃描程序集,找到所有插件類;
- 動態(tài)創(chuàng)建實(shí)例并調(diào)用方法。
示例代碼結(jié)構(gòu):
public interface IPlugin
{void Execute();
}[AttributeUsage(AttributeTargets.Class)]
public class PluginAttribute : Attribute { }[Plugin]
public class HelloPlugin : IPlugin
{public void Execute(){Console.WriteLine("你好,插件!");}
}class Program
{static void Main(){foreach (var type in Assembly.GetExecutingAssembly().GetTypes()){if (type.GetCustomAttributes(typeof(PluginAttribute), false).Length > 0 &&typeof(IPlugin).IsAssignableFrom(type)){var plugin = (IPlugin)Activator.CreateInstance(type);plugin.Execute();}}}
}
📝 小結(jié)
今天你學(xué)會了:
- 什么是 反射(Reflection),它在運(yùn)行時(shí)的作用;
- 如何使用反射動態(tài)獲取類型信息、創(chuàng)建實(shí)例、調(diào)用方法;
- 了解了 特性(Attribute) 的概念和用途;
- 學(xué)會定義和使用自定義特性;
- 掌握了如何結(jié)合反射與特性實(shí)現(xiàn)插件系統(tǒng)、自動注冊等功能;
- 編寫了一個(gè)完整的基于反射與特性的插件系統(tǒng)示例。
反射與特性是 C# 中非常強(qiáng)大的兩個(gè)機(jī)制,它們廣泛應(yīng)用于框架開發(fā)、自動化測試、ORM 工具、DI 容器等領(lǐng)域。
🧩 下一步學(xué)習(xí)方向(Day 21)
明天我們將進(jìn)入一個(gè)新的主題 —— 動態(tài)類型與動態(tài)語言運(yùn)行時(shí)(Dynamic Types & DLR),你將學(xué)會如何使用 dynamic
類型簡化反射操作,并理解它背后的原理。