各位.NET道友大家好,我是.NET修仙日记的掌门人,今天我们就来聊一聊
反射(Reflection)
,那么什么是反射(Reflection)
呢?接下来就和我一起来探索.NET修仙界的反射(Reflection)
神通……
一、反射神通的核心概念
1.1 什么是反射?
在.NET修真界,
反射(Reflection)
是程序自我探查、自我修改的无上神通。它允许我们在运行时:
探查类型信息(类、结构体、接口等)
动态创建对象实例
调用方法和访问属性
获取和操作特性(Attributes)
动态生成代码(通过Emit)
反射运行时
1.2 核心装配说明
反射的核心装配位于System.Reflection
命名空间,主要包含以下关键类型:
类型 | 说明 | 常用属性/方法 |
---|---|---|
Assembly | 代表程序集 | GetTypes() , GetModules() |
Module | 代表模块 | GetTypes() , GetFields() |
Type | 代表类型 | GetMethods() , GetProperties() |
MethodInfo | 方法信息 | Invoke() , ReturnType |
PropertyInfo | 属性信息 | GetValue() , SetValue() |
FieldInfo | 字段信息 | GetValue() , SetValue() |
2.基础反射操作
2.1 获取类型信息
// 三种获取Type对象的方式
Type t1 = typeof(string); // 通过typeof运算符
Type t2 = Type.GetType("System.String"); // 通过类型名称
Type t3 = "hello".GetType(); // 通过实例获取
Console.WriteLine($"类型名称:{t1.Name}");
Console.WriteLine($"命名空间:{t1.Namespace}");
Console.WriteLine($"是类吗?{t1.IsClass}");
Console.WriteLine($"基类型:{t1.BaseType}");
2.2 动态创建实例
动态创建实例示意图
// 创建不同类型的实例
object list = Activator.CreateInstance(typeof(List<string>));
object dt = Activator.CreateInstance(typeof(DateTime), 2023, 1, 1);
// 带参数的构造
Type sbType = typeof(StringBuilder);
StringBuilder sb = (StringBuilder)Activator.CreateInstance(
sbType,
new object[] { "初始值", 100 });
3.高级反射技巧
3.1 方法调用
// 获取并调用方法
Type mathType = typeof(Math);
MethodInfo maxMethod = mathType.GetMethod("Max",
new[] { typeof(int), typeof(int) });
int result = (int)maxMethod.Invoke(null, new object[] { 5, 10 });
Console.WriteLine($"最大值:{result}"); // 输出10
3.2 属性操作
属性操作示意图
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
// 反射操作属性
Person p = new Person();
Type personType = typeof(Person);
PropertyInfo nameProp = personType.GetProperty("Name");
nameProp.SetValue(p, "张三");
PropertyInfo ageProp = personType.GetProperty("Age");
ageProp.SetValue(p, 25);
Console.WriteLine($"{p.Name}, {p.Age}岁");
4.特性(Attribute)处理
4.1 自定义特性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = true)]
public class CultivationStageAttribute : Attribute
{
public string Stage { get; }
public int RequiredLevel { get; set; }
public CultivationStageAttribute(string stage)
{
Stage = stage;
}
}
4.2 特性探查
特性探查示意图
[CultivationStage("金丹期", RequiredLevel = 5)]
public class GoldenCoreTechnique
{
[CultivationStage("小成")]
public void Practice() { }
}
// 探查特性
Type techniqueType = typeof(GoldenCoreTechnique);
// 类级别特性
var classAttributes = techniqueType.GetCustomAttributes(
typeof(CultivationStageAttribute), false);
foreach(CultivationStageAttribute attr in classAttributes)
{
Console.WriteLine($"修炼阶段:{attr.Stage},要求等级:{attr.RequiredLevel}");
}
// 方法级别特性
MethodInfo method = techniqueType.GetMethod("Practice");
var methodAttributes = method.GetCustomAttributes(
typeof(CultivationStageAttribute), false);
// ...类似处理
5.性能优化
5.1 性能对比
性能对比示意图
5.2 优化策略
策略1:缓存反射对象
private static readonly Type _cachedType = typeof(MyClass);
private static readonly MethodInfo _cachedMethod = _cachedType.GetMethod("MyMethod");
策略2:使用委托
MethodInfo method = typeof(MyClass).GetMethod("MyMethod");
var del = (Func<MyClass, int>)Delegate.CreateDelegate(
typeof(Func<MyClass, int>), method);
int result = del(myInstance); // 比Invoke快10倍
策略3:表达式树编译
var param = Expression.Parameter(typeof(MyClass));
var call = Expression.Call(param, method);
var lambda = Expression.Lambda<Func<MyClass, int>>(call, param);
var compiled = lambda.Compile(); // 编译成委托
int result = compiled(myInstance); // 接近原生调用性能
6.Emit高级编程
6.1 IL代码生成
IL代码生成
6.2 动态方法示例
// 创建动态方法
var dynamicMethod = new DynamicMethod(
"DynamicAdd", // 方法名
typeof(int), // 返回类型
new[] { typeof(int), typeof(int) }, // 参数类型
typeof(Program).Module); // 关联模块
// 生成IL代码
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数
il.Emit(OpCodes.Ldarg_1); // 加载第二个参数
il.Emit(OpCodes.Add); // 执行加法
il.Emit(OpCodes.Ret); // 返回结果
// 创建并调用委托
var addDel = (Func<int, int, int>)dynamicMethod.CreateDelegate(
typeof(Func<int, int, int>));
int sum = addDel(5, 7); // 输出12
7.实战应用
7.1 插件系统实现
public interface IPlugin
{
string Name { get; }
void Execute();
}
public class PluginLoader
{
public List<IPlugin> LoadPlugins(string path)
{
var plugins = new List<IPlugin>();
foreach(string dll in Directory.GetFiles(path, "*.dll"))
{
Assembly assembly = Assembly.LoadFrom(dll);
foreach(Type type in assembly.GetTypes())
{
if(typeof(IPlugin).IsAssignableFrom(type) && !type.IsAbstract)
{
IPlugin plugin = (IPlugin)Activator.CreateInstance(type);
plugins.Add(plugin);
}
}
}
return plugins;
}
}
7.2 ORM框架示例
public class EntityMapper<T> where T : new()
{
public T Map(DbDataReader reader)
{
T entity = new T();
Type type = typeof(T);
for(int i = 0; i < reader.FieldCount; i++)
{
string name = reader.GetName(i);
PropertyInfo prop = type.GetProperty(name);
if(prop != null && !reader.IsDBNull(i))
{
object value = reader.GetValue(i);
prop.SetValue(entity, value);
}
}
return entity;
}
}
8.最佳实践
8.1 反射使用准则
-
避免滥用:只在真正需要动态行为的场景使用
-
性能敏感:高频调用路径避免使用反射
-
安全考虑:反射可以绕过访问限制,需谨慎
-
缓存优化:重复使用的反射对象要缓存
-
错误处理:反射调用要做好异常处理
8.2 替代方案
场景 | 反射方案 | 替代方案 |
---|---|---|
动态创建对象 | Activator.CreateInstance | 工厂模式 |
方法调用 | MethodInfo.Invoke | 委托/接口 |
属性访问 | PropertyInfo.Get/Set | 动态表达式 |
插件系统 | 反射加载 | DI容器 |
附录:常用反射工具方法
public static class ReflectionUtil
{
// 获取友好类型名称
public static string GetFriendlyTypeName(Type type)
{
if(!type.IsGenericType) return type.Name;
string name = type.Name.Split('`')[0];
var args = type.GetGenericArguments()
.Select(t => GetFriendlyTypeName(t));
return $"{name}<{string.Join(",", args)}>";
}
// 深度克隆对象
public static T DeepClone<T>(T obj)
{
if(obj == null) return default;
Type type = obj.GetType();
if(type.IsValueType || type == typeof(string))
return obj;
if(type.IsArray)
{
Array array = (Array)(object)obj;
Array cloned = (Array)array.Clone();
for(int i = 0; i < array.Length; i++)
cloned.SetValue(DeepClone(array.GetValue(i)), i);
return (T)(object)cloned;
}
T clonedObj = (T)Activator.CreateInstance(type);
foreach(FieldInfo field in type.GetFields(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
field.SetValue(clonedObj, DeepClone(field.GetValue(obj)));
}
return clonedObj;
}
}
结语
"反射之道,始于探查,精于动态,成于性能。初窥门径易,登堂入室难。望诸君勤加修炼,早日渡劫飞升!"
——.NET修仙日记
微信公众号【.NET修仙日记】