sweethome

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

之前设计一个管理系统开发框架的时候, 为了实现服务端模块化开发及权限验证的处理, 了解了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);
    }
}
posted on 2011-09-25 23:48  kingcomxu  阅读(379)  评论(0编辑  收藏  举报