zoukankan      html  css  js  c++  java
  • 转自CSDN(NqIceCoffee)的emit实现AOP, 收藏备忘

    之前设计一个管理系统开发框架的时候, 为了实现服务端模块化开发及权限验证的处理, 了解了AOP的概念, 也用entlib里的piab实现了业务模块的权限验证, 不过总感觉就为了一个小小的AOP需求引入entlib那么大的一个东西, 太过小题大作, 逛CSDN时看到这个方法很是喜欢, 转过来分享一下, 做轻量级的AOP应用应该很合适.

    原贴地址:http://topic.csdn.net/u/20110714/14/dbebf27e-42a7-42b8-9db1-63b7176dc8b8.html

    作者:NqIceCoffee

    核心代码:

    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);
        }
    }
  • 相关阅读:
    springboot文件上传: 单个文件上传 和 多个文件上传
    Eclipse:很不错的插件-devStyle,将你的eclipse变成idea风格
    springboot项目搭建:结构和入门程序
    POJ 3169 Layout 差分约束系统
    POJ 3723 Conscription 最小生成树
    POJ 3255 Roadblocks 次短路
    UVA 11367 Full Tank? 最短路
    UVA 10269 Adventure of Super Mario 最短路
    UVA 10603 Fill 最短路
    POJ 2431 Expedition 优先队列
  • 原文地址:https://www.cnblogs.com/sweethome/p/2190686.html
Copyright © 2011-2022 走看看