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