在上一篇文章
我们通过反射动态实现并继承了接口。
这一篇的内容延续上一篇继续扩展:给实现的类添加拦截器。
使用过 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);
}
}
第三步:调用
至此,简单的动态拦截器就实现成功了。