• 转自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);
        }
    }
  • 相关阅读:
    C语言程序设计I—第四周教学
    C语言程序设计I—第三周教学
    C语言程序设计I—第一周教学
    软工实践(四)——热词统计
    软工实践(三)——结对第一次作业(原型设计)
    软工实践(二)——构建之法读后感
    软工实践(一)——目标和规划
    庄子修身养性哲学
    $Matrix-Tree$定理-题目
    $Matrix-Tree$定理-理论
  • 原文地址:https://www.cnblogs.com/sweethome/p/2190686.html
Copyright © 2020-2023  润新知