自定义拦截器
1.自定义特性标记:通过
ExceptionInterceptorAttribute
标记需要进行异常处理的方法,并可通过属性配置处理方式

1 using System; 2 3 /// <summary> 4 /// 标记需要进行异常拦截的方法 5 /// </summary> 6 [AttributeUsage(AttributeTargets.Method, Inherited = true)] 7 public class ExceptionInterceptorAttribute : Attribute 8 { 9 // 可以添加属性配置异常处理方式 10 public bool LogException { get; set; } = true; 11 public bool RethrowException { get; set; } = true; 12 } 13
2.动态代理生成:
使用 System.Reflection.Emit
命名空间下的类动态生成代理类
代理类实现目标接口,并持有原始对象的引用
在生成的代理方法中加入 try-catch 块实现异常拦截


1 using System; 2 using System.Reflection; 3 using System.Reflection.Emit; 4 5 /// <summary> 6 /// 代理生成器,用于创建带有异常处理的代理类 7 /// </summary> 8 public static class ProxyGenerator 9 { 10 /// <summary> 11 /// 创建带有异常拦截的代理实例 12 /// </summary> 13 public static T CreateProxy<T>(T target) where T : class 14 { 15 if (target == null) 16 throw new ArgumentNullException(nameof(target)); 17 18 // 获取接口类型 19 Type interfaceType = typeof(T); 20 if (!interfaceType.IsInterface) 21 throw new InvalidOperationException("目标类型必须是接口"); 22 23 // 创建动态程序集和模块 24 AssemblyName assemblyName = new AssemblyName("DynamicProxyAssembly"); 25 AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly( 26 assemblyName, AssemblyBuilderAccess.Run); 27 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicProxyModule"); 28 29 // 定义代理类 30 TypeBuilder typeBuilder = moduleBuilder.DefineType( 31 $"{interfaceType.Name}Proxy", 32 TypeAttributes.Public | TypeAttributes.Class); 33 34 // 实现目标接口 35 typeBuilder.AddInterfaceImplementation(interfaceType); 36 37 // 添加目标对象字段 38 FieldBuilder targetField = typeBuilder.DefineField( 39 "_target", interfaceType, FieldAttributes.Private); 40 41 // 生成构造函数 42 GenerateConstructor(typeBuilder, targetField); 43 44 // 实现接口方法 45 ImplementInterfaceMethods(typeBuilder, interfaceType, targetField); 46 47 // 创建类型并实例化 48 Type proxyType = typeBuilder.CreateType(); 49 return Activator.CreateInstance(proxyType, target) as T; 50 } 51 52 // 生成构造函数 53 private static void GenerateConstructor(TypeBuilder typeBuilder, FieldBuilder targetField) 54 { 55 ConstructorInfo baseCtor = typeof(object).GetConstructor(Type.EmptyTypes); 56 ConstructorBuilder ctorBuilder = typeBuilder.DefineConstructor( 57 MethodAttributes.Public, CallingConventions.Standard, 58 new[] { targetField.FieldType }); 59 60 ILGenerator il = ctorBuilder.GetILGenerator(); 61 il.Emit(OpCodes.Ldarg_0); 62 il.Emit(OpCodes.Call, baseCtor); 63 il.Emit(OpCodes.Ldarg_0); 64 il.Emit(OpCodes.Ldarg_1); 65 il.Emit(OpCodes.Stfld, targetField); 66 il.Emit(OpCodes.Ret); 67 } 68 69 // 实现接口的所有方法 70 private static void ImplementInterfaceMethods(TypeBuilder typeBuilder, Type interfaceType, FieldBuilder targetField) 71 { 72 foreach (MethodInfo method in interfaceType.GetMethods()) 73 { 74 ImplementMethod(typeBuilder, method, targetField); 75 } 76 } 77 78 // 实现单个方法,添加异常处理逻辑 79 private static void ImplementMethod(TypeBuilder typeBuilder, MethodInfo method, FieldBuilder targetField) 80 { 81 // 检查方法是否有异常拦截特性 82 bool hasInterceptor = method.IsDefined(typeof(ExceptionInterceptorAttribute), true); 83 if (!hasInterceptor) 84 { 85 // 没有标记特性的方法直接调用目标对象方法 86 ImplementNormalMethod(typeBuilder, method, targetField); 87 return; 88 } 89 90 // 获取特性配置 91 var attribute = method.GetCustomAttribute<ExceptionInterceptorAttribute>(); 92 93 // 定义方法参数类型 94 Type[] parameterTypes = method.GetParameters() 95 .Select(p => p.ParameterType) 96 .ToArray(); 97 98 // 定义代理方法 99 MethodBuilder methodBuilder = typeBuilder.DefineMethod( 100 method.Name, 101 MethodAttributes.Public | MethodAttributes.Virtual, 102 method.ReturnType, 103 parameterTypes); 104 105 // 实现方法调用和异常处理 106 ILGenerator il = methodBuilder.GetILGenerator(); 107 108 // 创建异常处理块 109 Label tryStart = il.BeginExceptionBlock(); 110 111 // 调用目标对象的方法 112 il.Emit(OpCodes.Ldarg_0); 113 il.Emit(OpCodes.Ldfld, targetField); 114 115 // 加载方法参数 116 for (int i = 0; i < parameterTypes.Length; i++) 117 { 118 il.Emit(OpCodes.Ldarg, i + 1); 119 } 120 121 il.Emit(OpCodes.Callvirt, method); 122 123 // 正常退出 124 il.Emit(OpCodes.Leave, tryStart); 125 126 // 异常处理 127 il.BeginCatchBlock(typeof(Exception)); 128 129 // 存储异常对象到局部变量 130 LocalBuilder exception = il.DeclareLocal(typeof(Exception)); 131 il.Emit(OpCodes.Stloc, exception); 132 133 // 记录异常日志 134 if (attribute.LogException) 135 { 136 il.Emit(OpCodes.Ldstr, $"方法 {method.DeclaringType.Name}.{method.Name} 发生异常: {{{0}}}"); 137 il.Emit(OpCodes.Ldloc, exception); 138 il.Emit(OpCodes.Callvirt, typeof(Exception).GetProperty("Message").GetGetMethod()); 139 il.Emit(OpCodes.Call, typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) })); 140 il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); 141 } 142 143 // 重新抛出异常 144 if (attribute.RethrowException) 145 { 146 il.Emit(OpCodes.Ldloc, exception); 147 il.Emit(OpCodes.Throw); 148 } 149 else 150 { 151 // 如果不重新抛出,对于有返回值的方法需要返回默认值 152 if (method.ReturnType != typeof(void)) 153 { 154 il.Emit(OpCodes.Ldnull); 155 } 156 } 157 158 // 结束异常块 159 il.EndExceptionBlock(); 160 il.Emit(OpCodes.Ret); 161 162 // 将方法与接口方法关联 163 typeBuilder.DefineMethodOverride(methodBuilder, method); 164 } 165 166 // 实现没有异常拦截的方法 167 private static void ImplementNormalMethod(TypeBuilder typeBuilder, MethodInfo method, FieldBuilder targetField) 168 { 169 Type[] parameterTypes = method.GetParameters() 170 .Select(p => p.ParameterType) 171 .ToArray(); 172 173 MethodBuilder methodBuilder = typeBuilder.DefineMethod( 174 method.Name, 175 MethodAttributes.Public | MethodAttributes.Virtual, 176 method.ReturnType, 177 parameterTypes); 178 179 ILGenerator il = methodBuilder.GetILGenerator(); 180 181 // 直接调用目标对象的方法 182 il.Emit(OpCodes.Ldarg_0); 183 il.Emit(OpCodes.Ldfld, targetField); 184 185 for (int i = 0; i < parameterTypes.Length; i++) 186 { 187 il.Emit(OpCodes.Ldarg, i + 1); 188 } 189 190 il.Emit(OpCodes.Callvirt, method); 191 il.Emit(OpCodes.Ret); 192 193 typeBuilder.DefineMethodOverride(methodBuilder, method); 194 } 195 } 196
3.异常处理逻辑:
记录异常信息(方法名、异常消息等)
根据配置决定是否重新抛出异常
对有返回值的方法提供默认返回值支持


1 using System; 2 3 // 1. 定义服务接口 4 public interface IOrderService 5 { 6 [ExceptionInterceptor(LogException = true, RethrowException = true)] 7 void CreateOrder(int orderId, string customerName); 8 9 [ExceptionInterceptor(LogException = true, RethrowException = false)] 10 decimal CalculateTotal(decimal price, int quantity); 11 12 // 这个方法不会被拦截 13 string GetOrderStatus(int orderId); 14 } 15 16 // 2. 实现服务 17 public class OrderService : IOrderService 18 { 19 public void CreateOrder(int orderId, string customerName) 20 { 21 if (orderId <= 0) 22 throw new ArgumentException("订单ID必须大于0", nameof(orderId)); 23 24 if (string.IsNullOrEmpty(customerName)) 25 throw new ArgumentNullException(nameof(customerName), "客户名称不能为空"); 26 27 Console.WriteLine($"订单 {orderId} 创建成功,客户: {customerName}"); 28 } 29 30 public decimal CalculateTotal(decimal price, int quantity) 31 { 32 if (price < 0) 33 throw new InvalidOperationException("价格不能为负数"); 34 35 if (quantity <= 0) 36 throw new ArgumentOutOfRangeException(nameof(quantity), "数量必须大于0"); 37 38 return price * quantity; 39 } 40 41 public string GetOrderStatus(int orderId) 42 { 43 // 这个方法没有标记特性,不会被拦截 44 if (orderId <= 0) 45 throw new ArgumentException("无效的订单ID"); 46 47 return "已完成"; 48 } 49 } 50 51 // 3. 使用示例 52 class Program 53 { 54 static void Main(string[] args) 55 { 56 // 创建原始服务实例 57 IOrderService originalService = new OrderService(); 58 59 // 创建带有异常拦截的代理服务 60 IOrderService proxyService = ProxyGenerator.CreateProxy(originalService); 61 62 try 63 { 64 // 测试有拦截的方法 65 proxyService.CreateOrder(1001, "张三"); 66 proxyService.CalculateTotal(99.9m, 5); 67 68 // 测试异常情况 69 proxyService.CreateOrder(-1, null); // 会记录并重新抛出异常 70 } 71 catch (Exception ex) 72 { 73 Console.WriteLine($"捕获到异常: {ex.Message}"); 74 } 75 76 try 77 { 78 // 这个异常不会被重新抛出(RethrowException = false) 79 proxyService.CalculateTotal(-100, 5); 80 } 81 catch (Exception ex) 82 { 83 Console.WriteLine($"这里不会被执行,因为异常没有被重新抛出: {ex.Message}"); 84 } 85 86 try 87 { 88 // 这个方法没有拦截器,异常会直接抛出 89 proxyService.GetOrderStatus(-1); 90 } 91 catch (Exception ex) 92 { 93 Console.WriteLine($"未拦截的方法抛出异常: {ex.Message}"); 94 } 95 } 96 } 97