C#动态代理实现AOP

C#实现动态aop比较麻烦,需要用到IL中间语言的知识,笔者最近也在研究,在这记录和分享一下核心方法的解读,本人才疏学浅,如果错误还请指出

        /// <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);
        }

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页