在上一篇文章
反射的妙用:C#通过反射动态生成类型继承接口并实现
我们通过反射动态实现并继承了接口。
这一篇的内容延续上一篇继续扩展:给实现的类添加拦截器。
使用过 MVC 的小伙伴应该都知道 Filter,有请求/异常/返回/认证过滤器,今天我们要实现的拦截器可以理解为 Filter 中的请求过滤器。
第一步:先准备拦截器:
public class Intercept { /// <summary> /// 执行之前 /// </summary> /// <param name="methodName"></param> /// <param name="objs"></param> /// <returns></returns> public object Before(string methodName, object[] objs) { Console.WriteLine($"拦截的方法名:{methodName}"); for (int i = 0; i < objs.Length; i++) { Console.WriteLine("这是参数:" + objs[i]); } return "拦截成功"; } }
第二步:在上一篇动态生成的方法中加入调用拦截器的代码。
// 定义参数集合 var parameters = ilGen.DeclareLocal(typeof(object[])); ilGen.Emit(OpCodes.Ldc_I4, paramType.Length); // 定义新数组 var arr=new object[](); ilGen.Emit(OpCodes.Newarr, typeof(object)); // 将 parameters 推到栈顶 ilGen.Emit(OpCodes.Stloc, parameters); // 填充参数集合数据 for (var j = 0; j < paramType.Length; j++) { ilGen.Emit(OpCodes.Ldloc, parameters); ilGen.Emit(OpCodes.Ldc_I4, j); // 将下一个值的索引加载到堆栈上 ilGen.Emit(OpCodes.Ldarg, j + 1); // 将对应数组索引上的值替换 ilGen.Emit(OpCodes.Stelem_Ref); } ilGen.Emit(OpCodes.Ldarg_0); // 定义参数1 ilGen.Emit(OpCodes.Ldstr, targetMethod.Name); // 定义参数2 ilGen.Emit(OpCodes.Ldloc, parameters); // 调用拦截函数 ilGen.Emit(OpCodes.Callvirt, typeof(Intercept).GetMethod("Before")); // 判断是否需要返回值 if (methodBuilder.ReturnType == typeof(void)) { ilGen.Emit(OpCodes.Pop); } else { // 判断返回类型是否是值类型 if (methodBuilder.ReturnType.IsValueType) { ilGen.Emit(OpCodes.Unbox_Any, methodBuilder.ReturnType); } else { // 强制转换变量为指定类型(返回值 类型) ilGen.Emit(OpCodes.Castclass, methodBuilder.ReturnType); } }
第三步:调用
至此,简单的动态拦截器就实现成功了。
无绪分享