日期:2014-05-20 浏览次数:20491 次
private static void OverrideMethods(TypeBuilder tb, MethodInfo method) { if (!method.IsPublic|| !method.IsVirtual || IsObjectMethod(method)) return; Type[] paramTypes = GetParameterTypes(method); MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual; MethodBuilder mb = tb.DefineMethod(method.Name, attr, method.ReturnType, paramTypes); LocalBuilder result = null; ILGenerator il = mb.GetILGenerator(); bool is_void = method.ReturnType != typeof(void); if (is_void == false) result = il.DeclareLocal(method.ReturnType); object[] attrs = method.GetCustomAttributes(typeof(AspectAttribute), false); if (attrs != null) { //初始化所有当前方法用到的参数object[] CreateLocalParameterArr(il, paramTypes); //初始化AspectContext Type ctxType = typeof(AspectContext); ConstructorInfo info = ctxType.GetConstructor(Type.EmptyTypes); var ctx = il.DeclareLocal(ctxType); il.Emit(OpCodes.Newobj, info); il.Emit(OpCodes.Stloc, ctx); //给AspectContext的参数值属性ParameterArgs赋值 var propMethod = ctxType.GetMethod("set_ParameterArgs"); il.Emit(OpCodes.Ldloc, ctx); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, propMethod); int m = attrs.Length; LocalBuilder[] lbs = new LocalBuilder[m]; MethodInfo[] endInvokeMethods = new MethodInfo[m]; //初始化标记的横切对象,并调用横切对象的BeforeInvoke方法 for (int i = 0; i < m; i++) { var tmpType = attrs[i].GetType(); var aspect = il.DeclareLocal(tmpType); ConstructorInfo tmpInfo = tmpType.GetConstructor(Type.EmptyTypes); il.Emit(OpCodes.Newobj, tmpInfo); il.Emit(OpCodes.Stloc, aspect); var before_invoke_method = tmpType.GetMethod("BeforeInvoke"); endInvokeMethods[i] = tmpType.GetMethod("AfterInvoke"); il.Emit(OpCodes.Ldloc, aspect); il.Emit(OpCodes.Ldloc, ctx); il.Emit(OpCodes.Callvirt, before_invoke_method); il.Emit(OpCodes.Nop); lbs[i] = aspect; } //类对象,参数值依次入栈 for (int i = 0; i <= paramTypes.Length; i++) il.Emit(OpCodes.Ldarg, i); //调用基类的方法 il.Emit(OpCodes.Call, method); //如果有返回值,保存返回值到局部变量 if (is_void == false) il.Emit(OpCodes.Stloc, result); //调用横切对象的AfterInvoke方法 for (int i = 0; i < m; i++) { il.Emit(OpCodes.Ldloc, lbs[i]); il.Emit(OpCodes.Ldloc, ctx); il.Emit(OpCodes.Callvirt, endInvokeMethods[i]); il.Emit(OpCodes.Nop); } //如果有返回值,则把返回值压栈 if (is_void == false) il.Emit(OpCodes.Ldloc, result); //返回 il.Emit(OpCodes.Ret); } }