C# 反射完全指南:运行时类型发现、动态编程与特性读取
反射对象用于在运行时获取类型信息。提供访问运行中程序元数据的类位于 System.Reflection 命名空间。该命名空间包含类,允许获取应用程序信息、动态添加类型、值、对象。
反射应用场景
- 运行时查看特性信息
- 检查程序集中的各种类型并实例化
- 方法和属性的晚绑定
- 运行时创建新类型并执行任务
查看元数据
初始化 System.Reflection.MemberInfo 对象发现与类关联的特性:
System.Reflection.MemberInfo info = typeof(MyClass);
示例:读取类上的特性
using System;
[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute {
public readonly string Url;
public string Topic { get { return topic; } set { topic = value; } }
public HelpAttribute(string url) { this.Url = url; }
private string topic;
}
[HelpAttribute("Information on the class MyClass")]
class MyClass { }
namespace AttributeAppl {
class Program {
static void Main(string[] args) {
System.Reflection.MemberInfo info = typeof(MyClass);
object[] attributes = info.GetCustomAttributes(true);
for (int i = 0; i < attributes.Length; i++) {
System.Console.WriteLine(attributes[i]); // HelpAttribute
}
Console.ReadKey();
}
}
}
完整实战:读取 DeBugInfo 特性
using System;
using System.Reflection;
namespace BugFixApplication {
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Constructor |
AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute {
private int bugNo;
private string developer;
private string lastReview;
public string message;
public DeBugInfo(int bg, string dev, string d) {
bugNo = bg; developer = dev; lastReview = d;
}
public int BugNo { get { return bugNo; } }
public string Developer { get { return developer; } }
public string LastReview { get { return lastReview; } }
public string Message { get { return message; } set { message = value; } }
}
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
protected double length, width;
public Rectangle(double l, double w) { length = l; width = w; }
[DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
public double GetArea() { return length * width; }
[DeBugInfo(56, "Zara Ali", "19/10/2012")]
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle(4.5, 7.5);
r.Display();
Type type = typeof(Rectangle);
// 遍历类级特性
foreach (Object attributes in type.GetCustomAttributes(false)) {
DeBugInfo dbi = (DeBugInfo)attributes;
if (dbi != null) {
Console.WriteLine("Bug no: {0}", dbi.BugNo);
Console.WriteLine("Developer: {0}", dbi.Developer);
Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
Console.WriteLine("Remarks: {0}", dbi.Message);
}
}
// 遍历方法级特性
foreach (MethodInfo m in type.GetMethods()) {
foreach (Attribute a in m.GetCustomAttributes(true)) {
DeBugInfo dbi = (DeBugInfo)a;
if (dbi != null) {
Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name);
Console.WriteLine("Developer: {0}", dbi.Developer);
Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
Console.WriteLine("Remarks: {0}", dbi.Message);
}
}
}
Console.ReadLine();
}
}
}
输出:
Length: 4.5
Width: 7.5
Area: 33.75
Bug No: 49
Developer: Nuha Ali
Last Reviewed: 10/10/2012
Remarks: Unused variable
Bug No: 45
Developer: Zara Ali
Last Reviewed: 12/8/2012
Remarks: Return type mismatch
Bug No: 55, for Method: GetArea
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: Return type mismatch
Bug No: 56, for Method: Display
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks:
反射核心类
| 类 | 用途 |
|---|---|
Type | 类型声明的核心,获取类型信息 |
Assembly | 程序集加载、探索 |
MemberInfo | 成员基类(字段、属性、方法、事件等) |
MethodInfo | 方法信息、调用 |
PropertyInfo | 属性信息、读写 |
FieldInfo | 字段信息、读写 |
ConstructorInfo | 构造函数信息、创建实例 |
ParameterInfo | 参数信息 |
CustomAttributeData | 特性数据(无需实例化特性对象) |
常用反射操作
获取 Type 对象的三种方式
Type t1 = typeof(string); // 编译时已知类型
Type t2 = "hello".GetType(); // 运行时实例
Type t3 = Type.GetType("System.String"); // 字符串名称
创建实例
object obj = Activator.CreateInstance(type); // 无参构造
object obj = Activator.CreateInstance(type, args); // 有参构造
object obj = type.GetConstructor(types).Invoke(args); // 精确控制
调用方法
MethodInfo mi = type.GetMethod("MethodName");
object result = mi.Invoke(instance, parameters);
读写属性
PropertyInfo pi = type.GetProperty("PropertyName");
pi.SetValue(instance, value);
object val = pi.GetValue(instance);
性能与安全考量
- 反射比直接调用慢(
MethodInfo.Invoke有开销),热路径缓存MethodInfo/PropertyInfo - 使用
Delegate.CreateDelegate将反射调用转为委托提升性能 DynamicMethod/Expression Trees生成 IL 进一步优化- 反射可访问私有成员(
BindingFlags.NonPublic),破坏封装,慎用 - 部分信任环境受
ReflectionPermission限制
Source Generators 替代方案
C# 9.0+ 引入 Source Generators,编译时生成代码替代运行时反射,适合序列化、依赖注入、ORM 映射等场景,零运行时开销。
C语言