日期:2014-05-20  浏览次数:20491 次

【分享】纯手工打造Emit,实现AOP,附源码下载
比较喜欢Emit,所以就胡乱写点东西。这个是新鲜出炉的,分享给大家

AOP具体的原理我就不多讲了,大家可以查查资料,我这里用的【继承+重写+动态植入IL代码】

好了,废话少说,下载地址如下

http://download.csdn.net/source/3441835

在附上一个代码片段,嘿嘿。欢迎大虾拍砖

C# code
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);
            }
        }


------解决方案--------------------
好吧,我学习下
------解决方案--------------------
感谢分享。
------解决方案--------------------