private void EmitMethod(Type originType, TypeBuilder typeBuilder, MethodInfo baseMethod, FieldBuilder targetField) { Type[] argTypes = EmitHelper.GetParametersType(baseMethod); MethodInfo originMethod = ReflectionHelper.SearchMethod(originType, baseMethod.Name, argTypes); MethodBuilder methodBuilder = EmitHelper.DefineDerivedMethodSignature(typeBuilder, baseMethod); ILGenerator methodGen = methodBuilder.GetILGenerator(); methodGen.Emit(OpCodes.Ldarg_0); methodGen.Emit(OpCodes.Ldfld, targetField); int coventIndex = 0; foreach (ParameterInfo pi in originMethod.GetParameters()) { EmitHelper.LoadArg(methodGen, coventIndex + 1); EmitHelper.ConvertTopArgType(methodGen, argTypes[coventIndex], pi.ParameterType); coventIndex++; } methodGen.Emit(OpCodes.Callvirt, originMethod); methodGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, baseMethod); }
private void EmitMethod(Type originType, TypeBuilder typeBuilder, MethodInfo baseMethod, FieldBuilder targetField, FieldBuilder aopInterceptorField) { Type[] argTypes = EmitHelper.GetParametersType(baseMethod); MethodInfo originMethod = ReflectionHelper.SearchMethod(originType, baseMethod.Name, argTypes); MethodBuilder methodBuilder = EmitHelper.DefineDerivedMethodSignature(typeBuilder, baseMethod); ILGenerator methodGen = methodBuilder.GetILGenerator(); //Type[] genericTypes = new Type[1] ; LocalBuilder genericTypesLocalBuilder = methodGen.DeclareLocal(typeof(Type[])); if (originMethod.IsGenericMethod) { Type[] genericTypes = originMethod.GetGenericArguments(); methodGen.Emit(OpCodes.Ldc_I4, genericTypes.Length); methodGen.Emit(OpCodes.Newarr, typeof(Type)); methodGen.Emit(OpCodes.Stloc, genericTypesLocalBuilder); for (int i = 0; i < genericTypes.Length; i++) { methodGen.Emit(OpCodes.Ldloc, genericTypesLocalBuilder); methodGen.Emit(OpCodes.Ldc_I4, i); EmitHelper.LoadType(methodGen, genericTypes[i]); methodGen.Emit(OpCodes.Stelem_Ref); } } ParameterInfo[] paras = originMethod.GetParameters(); LocalBuilder paramNamesLocalBuilder = methodGen.DeclareLocal(typeof(string[])); LocalBuilder paramValuesLocalBuilder = methodGen.DeclareLocal(typeof(object[])); if (paras.Length > 0) { //调用 string[] paraNames = new string[] {"Add" ,"Insert" }; methodGen.Emit(OpCodes.Ldc_I4, paras.Length); methodGen.Emit(OpCodes.Newarr, typeof(string)); methodGen.Emit(OpCodes.Stloc, paramNamesLocalBuilder); for (int i = 0; i < paras.Length; i++) { methodGen.Emit(OpCodes.Ldloc, paramNamesLocalBuilder); methodGen.Emit(OpCodes.Ldc_I4, i); methodGen.Emit(OpCodes.Ldstr, paras[i].Name); methodGen.Emit(OpCodes.Stelem_Ref); } //调用 object[] paras = new object[] {a ,b }; methodGen.Emit(OpCodes.Ldc_I4, paras.Length); methodGen.Emit(OpCodes.Newarr, typeof(object)); methodGen.Emit(OpCodes.Stloc, paramValuesLocalBuilder); for (int i = 0; i < paras.Length; i++) { methodGen.Emit(OpCodes.Ldloc, paramValuesLocalBuilder); methodGen.Emit(OpCodes.Ldc_I4, i); methodGen.Emit(OpCodes.Ldarg, i + 1); if (paras[i].ParameterType.IsByRef) //如果是ref/out参数,则去地址 { EmitHelper.Ldind(methodGen, paras[i].ParameterType); methodGen.Emit(OpCodes.Box, paras[i].ParameterType.GetElementType()); } else if (paras[i].ParameterType.IsValueType) { methodGen.Emit(OpCodes.Box, paras[i].ParameterType); } else { } methodGen.Emit(OpCodes.Stelem_Ref); } } //调用 InterceptedMethod method = new InterceptedMethod(this.target, "InsertMuch", paras); LocalBuilder interceptedMethodLocalBuilder = methodGen.DeclareLocal(typeof(InterceptedMethod)); methodGen.Emit(OpCodes.Ldarg_0); methodGen.Emit(OpCodes.Ldfld, targetField); methodGen.Emit(OpCodes.Ldstr, originMethod.Name); methodGen.Emit(OpCodes.Ldloc, genericTypesLocalBuilder); methodGen.Emit(OpCodes.Ldloc, paramNamesLocalBuilder); methodGen.Emit(OpCodes.Ldloc, paramValuesLocalBuilder); methodGen.Emit(OpCodes.Newobj, typeof(InterceptedMethod).GetConstructor(new Type[] { typeof(object), typeof(string), typeof(Type[]), typeof(string[]), typeof(object[]) })); methodGen.Emit(OpCodes.Stloc, interceptedMethodLocalBuilder); //调用this.aopInterceptor.PreProcess(interceptedMethod); MethodInfo preProcessMethodInfo = typeof(IAopInterceptor).GetMethod("PreProcess", new Type[] { typeof(InterceptedMethod) }); methodGen.Emit(OpCodes.Ldarg_0); methodGen.Emit(OpCodes.Ldfld, aopInterceptorField); methodGen.Emit(OpCodes.Ldloc, interceptedMethodLocalBuilder); methodGen.Emit(OpCodes.Callvirt, preProcessMethodInfo); //调用 IArounder arounder = this.aopInterceptor.NewArounder(); LocalBuilder arounderLocalBuilder = methodGen.DeclareLocal(typeof(IArounder)); MethodInfo newArounderMethodInfo = typeof(IAopInterceptor).GetMethod("NewArounder"); methodGen.Emit(OpCodes.Ldarg_0); methodGen.Emit(OpCodes.Ldfld, aopInterceptorField); methodGen.Emit(OpCodes.Callvirt, newArounderMethodInfo); methodGen.Emit(OpCodes.Stloc, arounderLocalBuilder); //调用 arounder.BeginAround(method); MethodInfo beginAroundMethodInfo = typeof(IArounder).GetMethod("BeginAround"); methodGen.Emit(OpCodes.Ldloc, arounderLocalBuilder); methodGen.Emit(OpCodes.Ldloc, interceptedMethodLocalBuilder); methodGen.Emit(OpCodes.Callvirt, beginAroundMethodInfo); //调用 object returnVal = null; LocalBuilder retLocalBuilder = null; //是否有返回值 if (originMethod.ReturnType != typeof(void)) { retLocalBuilder = methodGen.DeclareLocal(originMethod.ReturnType); } LocalBuilder exceptionLocalBuilder = methodGen.DeclareLocal(typeof(Exception)); // try Label beginExceptionLabel = methodGen.BeginExceptionBlock(); //调用目标方法 methodGen.Emit(OpCodes.Ldarg_0); methodGen.Emit(OpCodes.Ldfld, targetField); int coventIndex = 0; foreach (ParameterInfo pi in originMethod.GetParameters()) { EmitHelper.LoadArg(methodGen, coventIndex + 1); EmitHelper.ConvertTopArgType(methodGen, argTypes[coventIndex], pi.ParameterType); coventIndex++; } methodGen.Emit(OpCodes.Callvirt, originMethod); if (retLocalBuilder != null) { methodGen.Emit(OpCodes.Stloc, retLocalBuilder); } // catch methodGen.BeginCatchBlock(typeof(Exception)); methodGen.Emit(OpCodes.Stloc, exceptionLocalBuilder); //存储Exception到local //调用 arounder.OnException(interceptedMethod ,exception); MethodInfo onExceptionMethodInfo = typeof(IArounder).GetMethod("OnException"); methodGen.Emit(OpCodes.Ldloc, arounderLocalBuilder); methodGen.Emit(OpCodes.Ldloc, interceptedMethodLocalBuilder); methodGen.Emit(OpCodes.Ldloc, exceptionLocalBuilder); methodGen.Emit(OpCodes.Callvirt, onExceptionMethodInfo); methodGen.Emit(OpCodes.Nop); methodGen.Emit(OpCodes.Rethrow); methodGen.Emit(OpCodes.Nop); methodGen.EndExceptionBlock(); //调用 arounder.EndAround(returnVal); MethodInfo endAroundMethodInfo = typeof(IArounder).GetMethod("EndAround"); methodGen.Emit(OpCodes.Ldloc, arounderLocalBuilder); if (retLocalBuilder != null) { if (originMethod.ReturnType.IsValueType) //返回值如果是值类型,则装箱后再调用EndAround { methodGen.Emit(OpCodes.Ldloc, retLocalBuilder); methodGen.Emit(OpCodes.Box, originMethod.ReturnType); } else { methodGen.Emit(OpCodes.Ldloc, retLocalBuilder); } } else { methodGen.Emit(OpCodes.Ldnull); } methodGen.Emit(OpCodes.Callvirt, endAroundMethodInfo); methodGen.Emit(OpCodes.Nop); //调用this.aopInterceptor.PostProcess(method ,returnVal); MethodInfo postProcessMethodInfo = typeof(IAopInterceptor).GetMethod("PostProcess", new Type[] { typeof(InterceptedMethod), typeof(object) }); methodGen.Emit(OpCodes.Ldarg_0); methodGen.Emit(OpCodes.Ldfld, aopInterceptorField); methodGen.Emit(OpCodes.Ldloc, interceptedMethodLocalBuilder); if (retLocalBuilder != null) { if (originMethod.ReturnType.IsValueType) { methodGen.Emit(OpCodes.Ldloc, retLocalBuilder); methodGen.Emit(OpCodes.Box, originMethod.ReturnType); } else { methodGen.Emit(OpCodes.Ldloc, retLocalBuilder); } } else { methodGen.Emit(OpCodes.Ldnull); } methodGen.Emit(OpCodes.Callvirt, postProcessMethodInfo); methodGen.Emit(OpCodes.Nop); if (retLocalBuilder != null) { methodGen.Emit(OpCodes.Ldloc, retLocalBuilder); } methodGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, baseMethod); }
private void EmitMethod(Type originType, TypeBuilder typeBuilder, MethodInfo baseMethod, FieldBuilder targetField, FieldBuilder exceptionFilterField) { Type[] argTypes = EmitHelper.GetParametersType(baseMethod); MethodInfo originMethod = ReflectionHelper.SearchMethod(originType, baseMethod.Name, argTypes); MethodBuilder methodBuilder = EmitHelper.DefineDerivedMethodSignature(typeBuilder, baseMethod); ILGenerator methodGen = methodBuilder.GetILGenerator(); LocalBuilder exceptionLocalBuilder = methodGen.DeclareLocal(typeof(Exception)); LocalBuilder retLocalBuilder = null; //是否有返回值 if (originMethod.ReturnType != typeof(void)) { retLocalBuilder = methodGen.DeclareLocal(originMethod.ReturnType); } Label beginExceptionLabel = methodGen.BeginExceptionBlock(); methodGen.Emit(OpCodes.Ldarg_0); methodGen.Emit(OpCodes.Ldfld, targetField); int converIndex = 0; foreach (ParameterInfo pi in originMethod.GetParameters()) { EmitHelper.LoadArg(methodGen, converIndex + 1); EmitHelper.ConvertTopArgType(methodGen, argTypes[converIndex], pi.ParameterType); converIndex++; } methodGen.Emit(OpCodes.Callvirt, originMethod);//调用目标方法 if (retLocalBuilder != null) { methodGen.Emit(OpCodes.Stloc_1); } methodGen.BeginCatchBlock(typeof(Exception)); methodGen.Emit(OpCodes.Stloc_0); //存储Exception到local string methodPath = originMethod.DeclaringType.ToString() + "." + originMethod.Name; // ESBasic.Helpers.TypeHelper.GetClassSimpleName(originMethod.DeclaringType) + "." + originMethod.Name; MethodInfo filterMethodInfo = typeof(IExceptionFilter).GetMethod("Filter", new Type[] { typeof(Exception), typeof(string), typeof(string) }); #region 构造methodParaInfo参数 //构造methodParaInfo string MethodInfo contactStringMethodInfo = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }); LocalBuilder methodParaInfoLocalBuilder = methodGen.DeclareLocal(typeof(string)); methodGen.Emit(OpCodes.Ldstr, "<Parameters>"); methodGen.Emit(OpCodes.Stloc, methodParaInfoLocalBuilder); int paraIndex = 0; foreach (ParameterInfo pi in originMethod.GetParameters()) { bool isByRef = false; Type paraType = pi.ParameterType; if (paraType.IsByRef) { paraType = paraType.GetElementType(); isByRef = true; } Label continueLabel = methodGen.DefineLabel(); MethodInfo toStringMethodInfo = paraType.GetMethod("ToString", new Type[] { }); //不能用typeof(object).GetMethod("ToString", new Type[] { }); if (toStringMethodInfo == null) //如果paraType为接口类型,则toStringMethodInfo为null { toStringMethodInfo = typeof(object).GetMethod("ToString", new Type[] { }); } if (!paraType.IsValueType) { EmitHelper.LoadArg(methodGen, paraIndex + 1); if (isByRef) { methodGen.Emit(OpCodes.Ldind_Ref); } methodGen.Emit(OpCodes.Ldnull); methodGen.Emit(OpCodes.Ceq); methodGen.Emit(OpCodes.Brtrue, continueLabel); } methodGen.Emit(OpCodes.Ldloc, methodParaInfoLocalBuilder); methodGen.Emit(OpCodes.Ldstr, string.Format("<{0}>", pi.Name)); methodGen.Emit(OpCodes.Call, contactStringMethodInfo); #region 调用ToString()方法 if (paraType.IsEnum) { EmitHelper.LoadArg(methodGen, paraIndex + 1); if (isByRef) { EmitHelper.Ldind(methodGen, paraType); } methodGen.Emit(OpCodes.Box, paraType); methodGen.Emit(OpCodes.Callvirt, toStringMethodInfo); } else if (paraType.IsValueType) { if (isByRef) { EmitHelper.LoadArg(methodGen, paraIndex + 1); } else { methodGen.Emit(OpCodes.Ldarga_S, paraIndex + 1); } methodGen.Emit(OpCodes.Call, toStringMethodInfo); } else { EmitHelper.LoadArg(methodGen, paraIndex + 1); if (isByRef) { EmitHelper.Ldind(methodGen, paraType); } methodGen.Emit(OpCodes.Callvirt, toStringMethodInfo); } #endregion methodGen.Emit(OpCodes.Call, contactStringMethodInfo); methodGen.Emit(OpCodes.Ldstr, string.Format("</{0}>", pi.Name)); methodGen.Emit(OpCodes.Call, contactStringMethodInfo); methodGen.Emit(OpCodes.Stloc, methodParaInfoLocalBuilder); methodGen.MarkLabel(continueLabel); ++paraIndex; } methodGen.Emit(OpCodes.Ldloc, methodParaInfoLocalBuilder); methodGen.Emit(OpCodes.Ldstr, "</Parameters>"); methodGen.Emit(OpCodes.Call, contactStringMethodInfo); methodGen.Emit(OpCodes.Stloc, methodParaInfoLocalBuilder); #endregion methodGen.Emit(OpCodes.Ldarg_0); methodGen.Emit(OpCodes.Ldfld, exceptionFilterField); methodGen.Emit(OpCodes.Ldloc_0); //加载Exception methodGen.Emit(OpCodes.Ldstr, methodPath); methodGen.Emit(OpCodes.Ldloc, methodParaInfoLocalBuilder); methodGen.Emit(OpCodes.Callvirt, filterMethodInfo); methodGen.Emit(OpCodes.Nop); methodGen.Emit(OpCodes.Rethrow); methodGen.Emit(OpCodes.Nop); methodGen.EndExceptionBlock(); if (retLocalBuilder != null) { methodGen.Emit(OpCodes.Ldloc_1); } methodGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, baseMethod); }
private void EmitMethod(Type originType, TypeBuilder typeBuilder, MethodInfo baseMethod, FieldBuilder targetField, FieldBuilder aopInterceptorField) { int num; Type[] parametersType = EmitHelper.GetParametersType(baseMethod); MethodInfo meth = ReflectionHelper.SearchMethod(originType, baseMethod.Name, parametersType); MethodBuilder methodInfoBody = EmitHelper.DefineDerivedMethodSignature(typeBuilder, baseMethod); ILGenerator iLGenerator = methodInfoBody.GetILGenerator(); LocalBuilder local = iLGenerator.DeclareLocal(typeof(Type[])); if (meth.IsGenericMethod) { Type[] genericArguments = meth.GetGenericArguments(); iLGenerator.Emit(OpCodes.Ldc_I4, genericArguments.Length); iLGenerator.Emit(OpCodes.Newarr, typeof(Type)); iLGenerator.Emit(OpCodes.Stloc, local); for (num = 0; num < genericArguments.Length; num++) { iLGenerator.Emit(OpCodes.Ldloc, local); iLGenerator.Emit(OpCodes.Ldc_I4, num); EmitHelper.LoadType(iLGenerator, genericArguments[num]); iLGenerator.Emit(OpCodes.Stelem_Ref); } } ParameterInfo[] parameters = meth.GetParameters(); LocalBuilder builder3 = iLGenerator.DeclareLocal(typeof(string[])); LocalBuilder builder4 = iLGenerator.DeclareLocal(typeof(object[])); if (parameters.Length > 0) { iLGenerator.Emit(OpCodes.Ldc_I4, parameters.Length); iLGenerator.Emit(OpCodes.Newarr, typeof(string)); iLGenerator.Emit(OpCodes.Stloc, builder3); for (num = 0; num < parameters.Length; num++) { iLGenerator.Emit(OpCodes.Ldloc, builder3); iLGenerator.Emit(OpCodes.Ldc_I4, num); iLGenerator.Emit(OpCodes.Ldstr, parameters[num].Name); iLGenerator.Emit(OpCodes.Stelem_Ref); } iLGenerator.Emit(OpCodes.Ldc_I4, parameters.Length); iLGenerator.Emit(OpCodes.Newarr, typeof(object)); iLGenerator.Emit(OpCodes.Stloc, builder4); for (num = 0; num < parameters.Length; num++) { iLGenerator.Emit(OpCodes.Ldloc, builder4); iLGenerator.Emit(OpCodes.Ldc_I4, num); iLGenerator.Emit(OpCodes.Ldarg, (int)(num + 1)); if (parameters[num].ParameterType.IsByRef) { EmitHelper.Ldind(iLGenerator, parameters[num].ParameterType); iLGenerator.Emit(OpCodes.Box, parameters[num].ParameterType.GetElementType()); } else if (parameters[num].ParameterType.IsValueType) { iLGenerator.Emit(OpCodes.Box, parameters[num].ParameterType); } iLGenerator.Emit(OpCodes.Stelem_Ref); } } LocalBuilder builder5 = iLGenerator.DeclareLocal(typeof(InterceptedMethod)); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, targetField); iLGenerator.Emit(OpCodes.Ldstr, meth.Name); iLGenerator.Emit(OpCodes.Ldloc, local); iLGenerator.Emit(OpCodes.Ldloc, builder3); iLGenerator.Emit(OpCodes.Ldloc, builder4); iLGenerator.Emit(OpCodes.Newobj, typeof(InterceptedMethod).GetConstructor(new Type[] { typeof(object), typeof(string), typeof(Type[]), typeof(string[]), typeof(object[]) })); iLGenerator.Emit(OpCodes.Stloc, builder5); MethodInfo method = typeof(IAopInterceptor).GetMethod("PreProcess", new Type[] { typeof(InterceptedMethod) }); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, aopInterceptorField); iLGenerator.Emit(OpCodes.Ldloc, builder5); iLGenerator.Emit(OpCodes.Callvirt, method); LocalBuilder builder6 = iLGenerator.DeclareLocal(typeof(IArounder)); MethodInfo info3 = typeof(IAopInterceptor).GetMethod("NewArounder"); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, aopInterceptorField); iLGenerator.Emit(OpCodes.Callvirt, info3); iLGenerator.Emit(OpCodes.Stloc, builder6); MethodInfo info4 = typeof(IArounder).GetMethod("BeginAround"); iLGenerator.Emit(OpCodes.Ldloc, builder6); iLGenerator.Emit(OpCodes.Ldloc, builder5); iLGenerator.Emit(OpCodes.Callvirt, info4); LocalBuilder builder7 = null; if (meth.ReturnType != typeof(void)) { builder7 = iLGenerator.DeclareLocal(meth.ReturnType); } LocalBuilder builder8 = iLGenerator.DeclareLocal(typeof(Exception)); Label label = iLGenerator.BeginExceptionBlock(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, targetField); int index = 0; foreach (ParameterInfo info5 in meth.GetParameters()) { EmitHelper.LoadArg(iLGenerator, index + 1); EmitHelper.ConvertTopArgType(iLGenerator, parametersType[index], info5.ParameterType); index++; } iLGenerator.Emit(OpCodes.Callvirt, meth); if (builder7 != null) { iLGenerator.Emit(OpCodes.Stloc, builder7); } iLGenerator.BeginCatchBlock(typeof(Exception)); iLGenerator.Emit(OpCodes.Stloc, builder8); MethodInfo info6 = typeof(IArounder).GetMethod("OnException"); iLGenerator.Emit(OpCodes.Ldloc, builder6); iLGenerator.Emit(OpCodes.Ldloc, builder5); iLGenerator.Emit(OpCodes.Ldloc, builder8); iLGenerator.Emit(OpCodes.Callvirt, info6); iLGenerator.Emit(OpCodes.Nop); iLGenerator.Emit(OpCodes.Rethrow); iLGenerator.Emit(OpCodes.Nop); iLGenerator.EndExceptionBlock(); MethodInfo info7 = typeof(IArounder).GetMethod("EndAround"); iLGenerator.Emit(OpCodes.Ldloc, builder6); if (builder7 != null) { if (meth.ReturnType.IsValueType) { iLGenerator.Emit(OpCodes.Ldloc, builder7); iLGenerator.Emit(OpCodes.Box, meth.ReturnType); } else { iLGenerator.Emit(OpCodes.Ldloc, builder7); } } else { iLGenerator.Emit(OpCodes.Ldnull); } iLGenerator.Emit(OpCodes.Callvirt, info7); iLGenerator.Emit(OpCodes.Nop); MethodInfo info8 = typeof(IAopInterceptor).GetMethod("PostProcess", new Type[] { typeof(InterceptedMethod), typeof(object) }); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, aopInterceptorField); iLGenerator.Emit(OpCodes.Ldloc, builder5); if (builder7 != null) { if (meth.ReturnType.IsValueType) { iLGenerator.Emit(OpCodes.Ldloc, builder7); iLGenerator.Emit(OpCodes.Box, meth.ReturnType); } else { iLGenerator.Emit(OpCodes.Ldloc, builder7); } } else { iLGenerator.Emit(OpCodes.Ldnull); } iLGenerator.Emit(OpCodes.Callvirt, info8); iLGenerator.Emit(OpCodes.Nop); if (builder7 != null) { iLGenerator.Emit(OpCodes.Ldloc, builder7); } iLGenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodInfoBody, baseMethod); }