コード例 #1
0
        /// <summary>
        /// TestAOPAttribute attribute = memberinfo.GetCustomAttributes(typeof(TestAOPAttribute), false)[0]
        /// </summary>
        /// <param name="cusAttr"></param>
        /// <param name="method"></param>
        /// <param name="module"></param>
        /// <param name="ilprosor"></param>
        /// <param name="varMethod"></param>
        private void GetAopAtrribute(InjectorArgs args, CustomAttribute cusAttr, VariableDefinition varAopAttribute)
        {
            var ilprosor = args.OriginMethod.Body.GetILProcessor();
            var module   = args.Module;

            Append(ilprosor, new[]
            {
                ilprosor.Create(OpCodes.Nop),
                ilprosor.Create(OpCodes.Ldloc, args.VarMemberInfo),
                //构造GetCustomAttributes两个参数
                ilprosor.Create(OpCodes.Ldtoken, cusAttr.AttributeType),
                ilprosor.Create(OpCodes.Call, module.Import(typeof(System.Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(System.RuntimeTypeHandle) }))),
                ilprosor.Create(OpCodes.Ldc_I4_0),  // 参数 false

                ilprosor.Create(OpCodes.Callvirt, module.Import(typeof(System.Reflection.MemberInfo).GetMethod("GetCustomAttributes", new Type[] { typeof(System.Type), typeof(bool) }))),
                ilprosor.Create(OpCodes.Ldc_I4_0),
                // Ldelem_Ref : 获取数组返回的第Index个元素
                // 更多解释及指令操作请自行查询msdn :  https://social.msdn.microsoft.com/Search/zh-CN?query=Ldelem_Ref&pgArea=header&emptyWatermark=true&ac=4
                ilprosor.Create(OpCodes.Ldelem_Ref),
                // Isinst 指令执行顺序
                //1. An object reference is pushed onto the stack.
                //2. The object reference is popped from the stack and tested to see if it is an instance of the class passed in class.
                //3. The result (either an object reference or a null reference) is pushed onto the stack.
                ilprosor.Create(OpCodes.Isinst, module.Import(cusAttr.AttributeType)), //cusAttr.AttributeType
                //ilprosor.Create(OpCodes.Ldc_I4,index),
                ilprosor.Create(OpCodes.Stloc, varAopAttribute),
                ilprosor.Create(OpCodes.Nop),
            });
        }
コード例 #2
0
        /// <summary>
        /// swith(exceptionStrategy){  case unthrow: break; ... }
        /// </summary>
        /// <param name="args"></param>
        /// <param name="method"></param>
        /// <param name="ilprosor"></param>
        private void InjectExceptionStrategy(InjectorArgs args)
        {
            var method   = args.OriginMethod;
            var ilprosor = args.ILProcessor;

            var breakSwitch = ilprosor.Create(OpCodes.Nop);
            //var caseUnThrow = ilprosor.Create(OpCodes.Nop);
            var caseUnThrow  = ilprosor.Create(OpCodes.Br, breakSwitch);
            var caseReThrow  = ilprosor.Create(OpCodes.Rethrow);
            var caseThrowNew = ilprosor.Create(OpCodes.Ldloc_S, args.VarException);

            //如果有多个AopAttibute 那只取attributes中Order排在第一的 ExceptionStrategy
            ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarAttrList));
            ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(MAList)
                                                                                   .GetMethod("First", new Type[] { }))));
            // ilprosor.Append(ilprosor.Create(OpCodes.Ldc_I4_0));
            //ilprosor.Append(ilprosor.Create(OpCodes.Ldelem_Ref));
            ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(MethodAspect)
                                                                                   .GetMethod("get_ExceptionStrategy", new Type[] { }))));
            ilprosor.Append(ilprosor.Create(OpCodes.Castclass, method.Module.Import(typeof(Int32))));
            ilprosor.Append(ilprosor.Create(OpCodes.Switch, new[] { caseUnThrow, caseThrowNew, caseReThrow, }));

            //注意这里需要执行两条 无条件跳转指令 Br
            ilprosor.Append(ilprosor.Create(OpCodes.Br, breakSwitch));
            ilprosor.Append(caseUnThrow);
            ilprosor.Append(caseThrowNew);
            ilprosor.Append(ilprosor.Create(OpCodes.Throw));
            ilprosor.Append(caseReThrow);
            ilprosor.Append(breakSwitch);
        }
コード例 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        private void InjectGetAopAttrList(InjectorArgs args)
        {
            //inject attribute.OnStart();
            var method     = args.OriginMethod;
            var ilprosor   = args.ILProcessor;
            var attributes = method.CustomAttributes.Where(a => IsSubClassOf(a.AttributeType.Resolve(), method.Module.Import(typeof(MethodAspect)).Resolve()));

            // 初始化 MAList attrList 用于存放attrite实例,在添加元素时就已经将元素按Order升序排序,
            // 如果使用IL实现排序就比较繁杂
            var varAttrList = new VariableDefinition(method.Module.Import(typeof(MAList)));

            method.Body.Variables.Add(varAttrList);
            ilprosor.Append(ilprosor.Create(OpCodes.Newobj, args.Module.Import(typeof(MAList).GetConstructor(new Type[] { }))));
            ilprosor.Append(ilprosor.Create(OpCodes.Stloc, varAttrList));
            args.VarAttrList = varAttrList;

            foreach (var attr in attributes)
            {
                //var varAopAttribute = new VariableDefinition(attr.AttributeType);
                var varAttribute = new VariableDefinition(args.Module.Import(attr.AttributeType));
                method.Body.Variables.Add(varAttribute);

                //TestAOPAttribute attribute = method.GetCustomAttributes(typeof(TestAOPAttribute), false)[0];
                GetAopAtrribute(args, attr, varAttribute);

                //attrList.Add(attr);
                ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarAttrList));
                ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, varAttribute));
                ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(MAList).
                                                                                       GetMethod("Add", new Type[] { typeof(MethodAspect) }))));
            }
        }
コード例 #4
0
        /// <summary>
        /// 注入代码  MemberInfo method = typeof(Class).GetMethod("TargetMethod", new Type[] { typeof(Class1), typeof(Class2), ... });
        /// </summary>
        /// <param name="method"></param>
        /// <param name="module"></param>
        /// <param name="ilprosor"></param>
        /// <param name="varTypeArr"></param>
        /// <param name="varMethod"></param>
        private void InjectGetMethod(InjectorArgs args)
        {
            var ilprosor   = args.OriginMethod.Body.GetILProcessor();
            var varTypeArr = new VariableDefinition(args.Module.Import(typeof(Type[])));
            var method     = args.OriginMethod;

            method.Body.Variables.Add(varTypeArr);
            // 注入typeof(Class) 并将方法字符串入栈
            Append(ilprosor, new[]
            {
                ilprosor.Create(OpCodes.Ldtoken, method.DeclaringType), // typeof(Class)
                ilprosor.Create(OpCodes.Call, method.Module.Import(typeof(System.Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(System.RuntimeTypeHandle) }))),
                ilprosor.Create(OpCodes.Ldstr, method.Name),
            });

            // 初始化  varTypeArr, 并将 varTypeArr 压栈
            // varTypeArr = new Type[] { typeof(Class1), typeof(Class2), ...)};
            InitTypeArr(method, method.Module, varTypeArr);

            //即实现方法 MemberInfo method = typeof(Class).GetMethod("TestMethod", new Type[] { typeof(Class1), typeof(Class2), ... });
            Append(ilprosor, new[]
            {
                ilprosor.Create(OpCodes.Call, method.Module.Import(typeof(System.Type).GetMethod("GetMethod", new Type[] { typeof(string), typeof(Type[]) }))),
                ilprosor.Create(OpCodes.Stloc, args.VarMemberInfo),
            });
        }
コード例 #5
0
        private void OverrideOriginMethod(MethodDefinition method, MethodDefinition newMethod)
        {
            var module   = method.Module;
            var ilprosor = method.Body.GetILProcessor();

            //OpCodes 请参考 https://msdn.microsoft.com/zh-cn/library/system.reflection.emit.opcodes_fields(v=vs.110).aspx

            var varMemberInfo = new VariableDefinition(module.Import(typeof(System.Reflection.MemberInfo)));
            var varAspectArgs = new VariableDefinition(module.Import(typeof(MethodAspectArgs)));

            method.Body.Variables.Add(varMemberInfo);
            method.Body.Variables.Add(varAspectArgs);

            var          handlerEnd = ilprosor.Create(OpCodes.Nop);
            InjectorArgs args       = new InjectorArgs(method, varMemberInfo, varAspectArgs);

            args.HandlerEnd = handlerEnd;
            args.NewMethod  = newMethod;

            ilprosor.Append(ilprosor.Create(OpCodes.Nop));

            // MemberInfo method = typeof(Class).GetMethod("TestMethod", new Type[] { typeof(Class1), typeof(Class2), ... });
            InjectGetMethod(args);

            //init MethodAspectArgs
            //MethodAspectArgs methodAspectArgs = new MethodAspectArgs();
            //methodAspectArgs.Argument = new object[]{ ... }
            InitMethodAspectArgs(args);

            //MAList list = new MAList();
            //TestAOPAttribute attribute = method.GetCustomAttributes(typeof(TestAOPAttribute), false)[0];
            //list.Add(attribute);
            InjectGetAopAttrList(args);

            // OnStart()
            InjectMethodOnEvent(args, "OnStart");

            // try{ call this.TargetMethod(...) } catch(Exception ex){  }
            TryCallTargetMethod(args);

            // OnEnd()
            InjectMethodOnEvent(args, "OnEnd");

            if (!method.ReturnType.FullName.Equals("System.Void"))
            {
                ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.ReturnValue));
            }
            ilprosor.Append(ilprosor.Create(OpCodes.Ret));
        }
コード例 #6
0
        private void InjectMethodOnEvent(InjectorArgs args, string eventName)
        {
            var ilprosor = args.ILProcessor;

            InjectForeach <MethodAspect>(args, args.VarAttrList, (current) =>
            {
                Append(ilprosor, new[]
                {
                    ilprosor.Create(OpCodes.Nop),
                    ilprosor.Create(OpCodes.Ldloc, current),
                    ilprosor.Create(OpCodes.Ldloc, args.VarAspectArgs),
                    ilprosor.Create(OpCodes.Callvirt, args.Module.Import(typeof(MethodAspect).
                                                                         GetMethod(eventName, new Type[] { typeof(MethodAspectArgs) }))),
                });
            });
        }
コード例 #7
0
        /// <summary>
        /// catch(Exception ex){  .... }
        /// </summary>
        /// <param name="args"></param>
        /// <param name="tryEnd"></param>
        private void InjectCatchBlock(InjectorArgs args, Instruction tryEnd)
        {
            var method   = args.OriginMethod;
            var ilprosor = method.Body.GetILProcessor();

            ilprosor.Append(tryEnd);

            // methodAspectArgs.Exception = ex;
            ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarAspectArgs));
            ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarException));
            ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(MethodAspectArgs)
                                                                                   .GetMethod("set_Exception", new Type[] { typeof(Exception) }))));

            InjectMethodOnEvent(args, "OnException");

            // swith(exceptionStrategy){  case unthrow: break; ... }
            InjectExceptionStrategy(args);
            // catch块退出,Leave指令必不可少
            // 若程序没有执行到catch部分则可以正常运行,但是通过ILSpy查看C#代码会报错:
            // Basci block has to end with unconditional control flow.
            ilprosor.Append(ilprosor.Create(OpCodes.Leave, args.HandlerEnd));
        }
コード例 #8
0
        private void TryCallTargetMethod(InjectorArgs args)
        {
            var method   = args.OriginMethod;
            var ilprosor = method.Body.GetILProcessor();

            var varException = new VariableDefinition(method.Module.Import(typeof(Exception)));

            method.Body.Variables.Add(varException);
            args.VarException = varException;

            var tryStart = ilprosor.Create(OpCodes.Nop);
            var tryEnd   = ilprosor.Create(OpCodes.Stloc, varException);

            // try {
            ilprosor.Append(tryStart);

            // this.TargetMethod(...);
            CallTargetMethod(args);

            InjectMethodOnEvent(args, "OnSuccess");

            ilprosor.Append(ilprosor.Create(OpCodes.Nop));
            ilprosor.Append(ilprosor.Create(OpCodes.Leave, args.HandlerEnd));

            // } catch(Exception ex) { ... }
            InjectCatchBlock(args, tryEnd);

            ilprosor.Append(args.HandlerEnd);
            ilprosor.Append(ilprosor.Create(OpCodes.Nop));
            // HandlerStart HandlerEnd 表示ExceptionHandlerType处理的开始及结束位置
            method.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                HandlerEnd   = args.HandlerEnd,
                HandlerStart = tryEnd,
                TryEnd       = tryEnd,
                TryStart     = tryStart,
                CatchType    = method.Module.Import(typeof(System.Exception))
            });
        }
コード例 #9
0
        private void CallTargetMethod(InjectorArgs args)
        {
            var method   = args.OriginMethod;
            var ilprosor = method.Body.GetILProcessor();

            if (!args.OriginMethod.IsStatic)
            {
                //Load this , arg0 指向的是当前对象,之后的参数指向的才是方法的入参
                ilprosor.Append(ilprosor.Create(OpCodes.Ldarg_0));
            }

            method.Parameters.ToList().ForEach(t => { ilprosor.Append(ilprosor.Create(OpCodes.Ldarg_S, t)); });

            ilprosor.Append(ilprosor.Create(OpCodes.Call, args.NewMethod));

            if (method.ReturnType.FullName != "System.Void")
            {
                args.ReturnValue = new VariableDefinition(method.ReturnType);
                method.Body.Variables.Add(args.ReturnValue);
                ilprosor.Append(ilprosor.Create(OpCodes.Stloc, args.ReturnValue));

                ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarAspectArgs));
                ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.ReturnValue));

                //设置返回值
                //判断返回类型类型是否是值类型  如果是值类型就装箱 引用类型就强转为object
                if (method.ReturnType.IsValueType)
                {
                    ilprosor.Append(ilprosor.Create(OpCodes.Box, method.ReturnType));
                }
                else
                {
                    ilprosor.Append(ilprosor.Create(OpCodes.Castclass, args.Module.Import(typeof(Object))));
                }
                ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(MethodAspectArgs)
                                                                                       .GetMethod("set_ReturnValue", new Type[] { typeof(Object) }))));
            }
        }
コード例 #10
0
        /// <summary>
        /// 初始化 OnStart  OnEnd参数 MethodAspectArgs
        /// </summary>
        /// <param name="method"></param>
        /// <param name="module"></param>
        /// <param name="varTypeArr"></param>
        private void InitMethodAspectArgs(InjectorArgs args)
        {
            var ilprosor = args.ILProcessor;
            var module   = args.Module;

            Append(ilprosor, new[]
            {
                ilprosor.Create(OpCodes.Nop),
                ilprosor.Create(OpCodes.Newobj, module.Import(typeof(MethodAspectArgs).GetConstructor(new Type[] {}))),  // typeof(object[])
                ilprosor.Create(OpCodes.Stloc, args.VarAspectArgs),
            });

            if (args.OriginMethod.Parameters.Count > 0)
            {
                ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarAspectArgs));
                InitObjectArr(args.OriginMethod, module, ilprosor);
                Append(ilprosor, new[]
                {
                    ilprosor.Create(OpCodes.Callvirt, module.Import(typeof(MethodAspectArgs)
                                                                    .GetMethod("set_Argument", new Type[] { typeof(Object[]) }))),
                }
                       );
            }
        }
コード例 #11
0
        private void InjectForeach <T>(InjectorArgs args, VariableDefinition list, Action <VariableDefinition> action)
        {
            MethodDefinition method   = args.OriginMethod;
            ILProcessor      ilprosor = args.ILProcessor;

            // 初始化变量
            if (!_foreachItemDic.ContainsKey(typeof(IEnumerator <T>)) || args.VarEnumerator == null)
            {
                args.VarEnumerator = new VariableDefinition(method.Module.Import(typeof(IEnumerator <T>)));
                method.Body.Variables.Add(args.VarEnumerator);
                if (!_foreachItemDic.ContainsKey(typeof(IEnumerator <T>)))
                {
                    _foreachItemDic.Add(typeof(IEnumerator <T>), true);
                }
            }
            if (args.VarHasNext == null)
            {
                args.VarHasNext = new VariableDefinition(method.Module.Import(typeof(bool)));
                method.Body.Variables.Add(args.VarHasNext);
            }
            if (!_foreachItemDic.ContainsKey(typeof(T)) || args.VarItem == null)
            {
                args.VarItem = new VariableDefinition(method.Module.Import(typeof(T)));
                method.Body.Variables.Add(args.VarItem);
                if (!_foreachItemDic.ContainsKey(typeof(T)))
                {
                    _foreachItemDic.Add(typeof(T), true);
                }
            }

            var tryStart   = ilprosor.Create(OpCodes.Nop);
            var handlerEnd = ilprosor.Create(OpCodes.Nop);
            var tryEnd     = ilprosor.Create(OpCodes.Nop);
            //var tryEnd = ilprosor.Create(OpCodes.Leave, handlerEnd);
            var finallyStart = ilprosor.Create(OpCodes.Nop);
            var finallyEnd   = ilprosor.Create(OpCodes.Endfinally);

            //  list.GetEnumerator()
            ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, list));
            ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(MAList).GetMethod("GetEnumerator", new Type[] { }))));
            ilprosor.Append(ilprosor.Create(OpCodes.Stloc, args.VarEnumerator));
            // 注意顺序 只有获取到VarEnumerator才可以初始化以下指令
            var loopStart     = ilprosor.Create(OpCodes.Ldloc, args.VarEnumerator);
            var moveNextStart = ilprosor.Create(OpCodes.Ldloc, args.VarEnumerator);

            // try{  while(list.MoveNext()){  var item = list.get_Current();  action(item);   }   }
            ilprosor.Append(tryStart);
            ilprosor.Append(ilprosor.Create(OpCodes.Br, moveNextStart));
            ilprosor.Append(loopStart);
            ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(IEnumerator <T>).GetMethod("get_Current", new Type[] { }))));
            ilprosor.Append(ilprosor.Create(OpCodes.Stloc, args.VarItem));

            if (action != null)
            {
                action(args.VarItem);
            }

            ilprosor.Append(moveNextStart);
            ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(IEnumerator).GetMethod("MoveNext", new Type[] { }))));
            ilprosor.Append(ilprosor.Create(OpCodes.Stloc, args.VarHasNext));
            ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarHasNext));
            ilprosor.Append(ilprosor.Create(OpCodes.Brtrue, loopStart));
            ilprosor.Append(ilprosor.Create(OpCodes.Leave, handlerEnd));

            //
            // finally{
            //  if( VarEnumerator!=null )
            //  { VarEnumerator.Dispose(); }
            // }
            ilprosor.Append(finallyStart);
            ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarEnumerator));
            ilprosor.Append(ilprosor.Create(OpCodes.Ldnull));
            ilprosor.Append(ilprosor.Create(OpCodes.Ceq));
            ilprosor.Append(ilprosor.Create(OpCodes.Stloc_S, args.VarHasNext));
            ilprosor.Append(ilprosor.Create(OpCodes.Ldloc_S, args.VarHasNext));
            ilprosor.Append(ilprosor.Create(OpCodes.Brtrue_S, handlerEnd));
            ilprosor.Append(ilprosor.Create(OpCodes.Ldloc, args.VarEnumerator));
            ilprosor.Append(ilprosor.Create(OpCodes.Callvirt, method.Module.Import(typeof(System.IDisposable).GetMethod("Dispose", new Type[] { }))));
            ilprosor.Append(ilprosor.Create(OpCodes.Nop));
            ilprosor.Append(finallyEnd);
            ilprosor.Append(handlerEnd);

            //ilprosor.Append(end);
            ilprosor.Append(ilprosor.Create(OpCodes.Nop));
            // HandlerStart HandlerEnd 表示ExceptionHandlerType处理的开始及结束位置
            method.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Finally)
            {
                HandlerEnd   = handlerEnd,
                HandlerStart = finallyStart,
                TryEnd       = finallyStart,
                TryStart     = tryStart
            });
        }