自:
https://blog.csdn.net/weixin_37390956/article/details/79947976
搬砖,
-------------------- /// <summary> /// 创建动态代理方法 /// </summary> /// <param name="typeBuilder">类型构造器</param> /// <param name="method">方法元数据</param> /// <param name="realObjectField">实际对象</param> /// <param name="aspectFields">切面</param> private static void EmitMethod(TypeBuilder typeBuilder, MethodInfo method, FieldBuilder realObjectField, List<AspectField> aspectFields) { //参数列表 var parameters = method.GetParameters(); //动态实例 var emitter = Sigil.NonGeneric.Emit.BuildInstanceMethod(method.ReturnType, parameters.Select(i => i.ParameterType).ToArray(), typeBuilder, method.Name, MethodAttributes.Public | MethodAttributes.Virtual); //label base var lbCallBase = emitter.DefineLabel(); //label return var lbReturn = emitter.DefineLabel(); //方法上下文 var methodContextLocal = emitter.DeclareLocal(typeof(MethodContext)); //返回 var returnLocal = method.ReturnType != typeof(void) ? emitter.DeclareLocal(method.ReturnType) : null; //本地存储 var objArrayLocal = emitter.DeclareLocal(typeof(object[])); //异常 var exceptionLocal = emitter.DeclareLocal<Exception>(); //切面列表 var aspects = method.GetCustomAttributes(typeof(AspectAttribute), false).Cast<AspectAttribute>().Concat(AspectFactory.GlobalAspects).ToList(); //是否包含异常切面 bool hasException = aspects.Any(i => i.GetType().GetMethod("ExceptionFilter").DeclaringType != typeof(AspectAttribute)); //异常捕捉块 Sigil.ExceptionBlock tryBlock = null; //方法名 string methodName = method.Name; if (aspects.Any()) { //给参数分配内存 emitter .LoadConstant(parameters.Length) .NewArray<object>() .StoreLocal(objArrayLocal); // var parameters = new object[parameters.Length]; //给参数填充实际值 for (int i = 0; i < parameters.Length; i++) { emitter .LoadLocal(objArrayLocal) .LoadConstant(i) .LoadArgument((ushort)(i + 1)) .Box(parameters[i].ParameterType, true) .StoreElement<object>(); // parameters[i] = paramN; } //通过使用该方法的内部元数据表示形式 (句柄) 获取方法的信息 emitter .LoadConstant(method) .Call(typeof(MethodBase).GetMethod("GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle) })) .CastClass<MethodInfo>() // methodof(Method) //加载真实方法对象 .LoadArgument(0) .LoadField(realObjectField) // this.realObject //加载自定义的上下文 .LoadLocal(objArrayLocal) .Call(typeof(ProxyBase).GetMethod("GetMethodContext", BindingFlags.Static | BindingFlags.NonPublic)) .StoreLocal(methodContextLocal); // methodContextLocal = GetMethodContext(methodof(Method), this.realObject, parameters } var currentMethodAspects = new List<AspectField>(); //根据切面的优先级排序 foreach (var aspect in aspects.OrderBy(i => i.EnterPriority)) { //创建切面 var field = typeBuilder.DefineField("aspectField_" + Guid.NewGuid(), typeof(AspectAttribute), FieldAttributes.Static | FieldAttributes.Private); aspectFields.Add(new AspectField { Aspect = aspect, Field = field }); currentMethodAspects.Add(new AspectField { Aspect = aspect, Field = field }); //调用切面前处理 emitter .LoadField(field) .LoadLocal(methodContextLocal) .CallVirtual(typeof(AspectAttribute).GetMethod(GetName(aspect.MethodEnter), BindingFlags.Instance | BindingFlags.Public)); //如果方法有返回则试图获取 返回值 返回如果不为空则标志lbreturn 直接返回结束 if (method.ReturnType != typeof(void)) { emitter .LoadLocal(methodContextLocal) .Call(typeof(MethodContext).GetProperty("ReturnValue").GetGetMethod()) .BranchIfTrue(lbReturn); } } //Chama o método base 标记调用父方法 emitter.MarkLabel(lbCallBase); //如果包含异常捕捉切面则添加一个trycatch块 if (hasException) tryBlock = emitter.BeginExceptionBlock(); if (aspects.Any() && method.ReturnType != typeof(void)) //Armazena o objeto retornado no ReturnValue caso haja aspectos emitter.LoadLocal(methodContextLocal); emitter .LoadArgument(0) .LoadField(realObjectField); for (int i = 0; i < parameters.Length; i++) emitter.LoadArgument((ushort)(i + 1)); //调用实际的方法 emitter.CallVirtual(method); //realObject.Method(parameters...); //保存返回值 if (method.ReturnType != typeof(void)) emitter.StoreLocal(returnLocal); //Armazena o objeto retornado no ReturnValue caso haja aspectos //设置methodcontext里的返回值 if (method.ReturnType != typeof(void) && aspects.Any()) { emitter .LoadLocal(returnLocal) .Box(method.ReturnType, true) .Call(typeof(MethodContext).GetProperty("ReturnValue").GetSetMethod()); } //开始调用切面里面的异常处理 if (hasException) { var catchBlock = emitter.BeginCatchBlock<Exception>(tryBlock); emitter.StoreLocal(exceptionLocal); foreach (var aspect in currentMethodAspects.Where(i => i.Aspect.GetType().GetMethod("ExceptionFilter").DeclaringType != typeof(AspectAttribute))) emitter .LoadField(aspect.Field) .LoadLocal(methodContextLocal) .LoadLocal(exceptionLocal) .CallVirtual(typeof(AspectAttribute).GetMethod("ExceptionFilter", BindingFlags.Instance | BindingFlags.Public)); //切面异常处理结束之后重新抛出异常 不影响后续流程 emitter .ReThrow() .EndCatchBlock(catchBlock) .EndExceptionBlock(tryBlock); } //循环按照优先级调用切面后处理 emitter.MarkLabel(lbReturn); foreach (var aspect in currentMethodAspects.OrderBy(i => i.Aspect.ExitPriority)) { emitter .LoadField(aspect.Field) .LoadLocal(methodContextLocal) .CallVirtual(typeof(AspectAttribute).GetMethod(GetName(aspect.Aspect.MethodExit), BindingFlags.Instance | BindingFlags.Public)); } //存储返回值 if (method.ReturnType != typeof(void)) { if (aspects.Any()) { emitter .LoadLocal(methodContextLocal) .Call(typeof(MethodContext).GetProperty("ReturnValue").GetGetMethod()) .UnboxAny(method.ReturnType, true) .StoreLocal(returnLocal); } if (method.ReturnType != typeof(void)) emitter.LoadLocal(returnLocal); } //返回 emitter.Return(); //生成代理方法 var newMethod = emitter.CreateMethod(); typeBuilder.DefineMethodOverride(newMethod, method); }--------------------- 作者:我们生活在果壳中 来源: 原文:https://blog.csdn.net/weixin_37390956/article/details/79947976
----------------------
其他参考,,,AOP从静态代理到动态代理(Emit实现)详解 (这篇不错): https://www.jb51.net/article/147526.htm
转载于:https://www.cnblogs.com/ijunxiong/articles/10149327.html
相关资源:C# .net Aop 动态截获异常