zoukankan      html  css  js  c++  java
  • 使用IL 生成Aop代码

      1.先看如何调用,以及类的定义

     

     

     执行结果如下:

     生成代码类的代码如下:

        public class AopFactory
        {
            public static I CreateAopObj<I, T>() where T : class, new() where I : class
            {
                return AopCreater<I, T>.Create();
            }
            public class AopCreater<I, T> where T : class, new() where I : class
            {
                public static Func<I> Create = CreateAopObj();
                private static Func<I> CreateAopObj()
                {
                    //动态生成
                    var typeT = typeof(T);
                    var typeI = typeof(I);
                    AssemblyName asmName = new AssemblyName("ILGratorTest");
                    //创建程序集
                    var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave);
                    //创建模块
                    var module = asmBuilder.DefineDynamicModule(asmName.Name, asmName.Name + ".dll");
                    //生成代理类
                    var typeBuilder = module.DefineType(typeT.Name + "_Aop", TypeAttributes.Public, null, new Type[] { typeI });
                    //保存代理对象,并在构造函数的时候赋值
                    var aopObjField = typeBuilder.DefineField("aop_" + typeT.Name, typeT, FieldAttributes.Private);
                    //生成构造函数
                    var tbCon = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
    
                    var ilCon = tbCon.GetILGenerator();
                    ilCon.Emit(OpCodes.Ldarg_0);
                    ilCon.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
                    ilCon.Emit(OpCodes.Ldarg_0);
                    ilCon.Emit(OpCodes.Newobj, typeT.GetConstructor(Type.EmptyTypes));
                    ilCon.Emit(OpCodes.Stfld, aopObjField);
                    ilCon.Emit(OpCodes.Ret);
    
                    //获取要代理的方法
                    var methods = typeI.GetMethods(BindingFlags.SuppressChangeType | BindingFlags.Instance | BindingFlags.Public);
                    //定义方法IL
                    for (int i = 0; i < methods.Length; i++)
                    {
                        var currentMthod = methods[i];
                        var methodTypes = currentMthod.GetParameters().Select(d => d.ParameterType).ToArray();
                        var method = typeBuilder.DefineMethod(currentMthod.Name, MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual, currentMthod.ReturnType, methodTypes);
                        //生成上下文对象 AopContext
                        var methIl = method.GetILGenerator();
                        var localobjs = methIl.DeclareLocal(typeof(object[]));
                        methIl.Emit(OpCodes.Ldc_I4, methodTypes.Length);
                        methIl.Emit(OpCodes.Newarr, typeof(object));
                        methIl.Emit(OpCodes.Stloc, localobjs);
    
                        for (int valIndex = 0; valIndex < methodTypes.Length; valIndex++)
                        {
                            //加载局部变量
                            methIl.Emit(OpCodes.Ldloc, localobjs);
                            methIl.Emit(OpCodes.Ldc_I4, valIndex);
                            methIl.Emit(OpCodes.Ldarg, valIndex + 1);
                            if (methodTypes[valIndex].IsValueType)
                                methIl.Emit(OpCodes.Box, methodTypes[valIndex]);
                            methIl.Emit(OpCodes.Stelem_Ref);
                        }
                        bool isNoReturn = true;
                        //1.设置局部变量
                        var locContext = methIl.DeclareLocal(typeof(AopContext));
                        LocalBuilder locReturn = null;
                        if (currentMthod.ReturnType != typeof(void))
                        {
                            isNoReturn = false;
                            locReturn = methIl.DeclareLocal(currentMthod.ReturnType);
                        }
    
                        methIl.Emit(OpCodes.Newobj, typeof(AopContext).GetConstructor(Type.EmptyTypes));
                        methIl.Emit(OpCodes.Stloc, locContext);
                        //1.1保存参数值到上下文中
                        var fild = typeof(AopContext).GetField("Paramter");
                        methIl.Emit(OpCodes.Ldloc, locContext);
                        methIl.Emit(OpCodes.Ldloc, localobjs);
                        methIl.Emit(OpCodes.Stfld, fild);
    
                        //2.找到方法上面的特性
                        var aopAttrType = typeof(AopAttribute);
                        var methodBefore = aopAttrType.GetMethod("BeforeInvoke");
                        var methodAfter = aopAttrType.GetMethod("AfterInvoke");
    
                        var aopAttribute = typeT.GetMethod(currentMthod.Name).GetCustomAttributes().Where(d => aopAttrType.IsAssignableFrom(d.GetType())).Cast<AopAttribute>().OrderBy(d => d.Sort).ToArray();
                        List<LocalBuilder> listAopLocalBuilder = new List<LocalBuilder>();
    
                        for (int aopAIndex = 0; aopAIndex < aopAttribute.Length; aopAIndex++)
                        {
                            //定义局部变量生成他们
                            var attrType = (aopAttribute[aopAIndex]).GetType();
                            var locAttribute = methIl.DeclareLocal(attrType);
                            methIl.Emit(OpCodes.Newobj, attrType.GetConstructor(Type.EmptyTypes));
                            methIl.Emit(OpCodes.Stloc, locAttribute);
                            //调用局部变量的BeforeInvoke  方法
                            methIl.Emit(OpCodes.Ldloc, locAttribute);
                            methIl.Emit(OpCodes.Ldloc, locContext);
                            methIl.Emit(OpCodes.Callvirt, methodBefore);
                            listAopLocalBuilder.Add(locAttribute);
                        }
                        #region 异常代码块
    
                        methIl.BeginExceptionBlock();
                        //3.执行原来的方法
                        //aopObjField
                        methIl.Emit(OpCodes.Ldarg_0);
                        methIl.Emit(OpCodes.Ldfld, aopObjField);
                        for (int argIndex = 0; argIndex < methodTypes.Length; argIndex++)
                        {
                            methIl.Emit(OpCodes.Ldarg, argIndex + 1);
                        }
                        methIl.Emit(OpCodes.Call, currentMthod);
    
                        //4.判断原方法是否有返回值
                        if (currentMthod.ReturnType != typeof(void))
                        {
                            var fildReturn = typeof(AopContext).GetField("ReturnObj");
                            //保存返回值
                            methIl.Emit(OpCodes.Stloc, locReturn);
                            methIl.Emit(OpCodes.Ldloc, locContext);
                            methIl.Emit(OpCodes.Ldloc, locReturn);
                            methIl.Emit(OpCodes.Stfld, fildReturn);
                        }
                        methIl.BeginCatchBlock(typeof(Exception));
                        //保存变量的值先
                        var exception = methIl.DeclareLocal(typeof(Exception));
                        methIl.Emit(OpCodes.Stloc, exception);
    
                        var methodCath = aopAttrType.GetMethod("CatchInvoke");
                        var locAopExcption = methIl.DeclareLocal(typeof(AopException));
                        //生成异常对象
                        methIl.Emit(OpCodes.Newobj, typeof(AopException).GetConstructor(Type.EmptyTypes));
                        methIl.Emit(OpCodes.Stloc, locAopExcption);
    
                        //设置他的属性
                        methIl.Emit(OpCodes.Ldloc, locAopExcption);
                        methIl.Emit(OpCodes.Ldloc, exception);
                        methIl.Emit(OpCodes.Stfld, typeof(AopException).GetField("Exception"));
    
                        //调用异常方法
    
                        for (int aopAIndex2 = 0; aopAIndex2 < aopAttribute.Length; aopAIndex2++)
                        {
                            methIl.Emit(OpCodes.Ldloc, listAopLocalBuilder[aopAIndex2]);
                            methIl.Emit(OpCodes.Ldloc, locAopExcption);
                            methIl.Emit(OpCodes.Callvirt, methodCath);
                        }
    
                        methIl.EndExceptionBlock();
                        #endregion
                        //调用AfterInvoke方法
                        for (int aopAIndex = 0; aopAIndex < aopAttribute.Length; aopAIndex++)
                        {
                            //调用局部变量的BeforeInvoke  方法
                            methIl.Emit(OpCodes.Ldloc, listAopLocalBuilder[aopAIndex]);
                            methIl.Emit(OpCodes.Ldloc, locContext);
                            methIl.Emit(OpCodes.Callvirt, methodAfter);
                        }
                        if (!isNoReturn)
                        {
                            methIl.Emit(OpCodes.Ldloc, locReturn);
                        }
                        methIl.Emit(OpCodes.Ret);
    
                    }
                    var builedType = typeBuilder.CreateType();
                    asmBuilder.Save(asmName.Name + ".dll");
    
                    var methoddy = new DynamicMethod("createNewObj", typeI, null);
    
                    var il1 = methoddy.GetILGenerator();
                    il1.Emit(OpCodes.Newobj, builedType.GetConstructor(Type.EmptyTypes));
                    il1.Emit(OpCodes.Ret);
                    return methoddy.CreateDelegate(typeof(Func<I>)) as Func<I>;
                }
            }
        }

    生成的代理对象如下:

       代码下载

  • 相关阅读:
    20 数组和指针
    19 数组、指针
    18 # 和 ##
    17 pragma
    4 类族结构的改进
    css常用标签
    帝国cms 通过文章的id获取信息
    帝国cms 获取一条数据,但是从第二条开始获取
    帝国cms 描述和关键词动态获取
    导入高德地图快捷链接导入方法
  • 原文地址:https://www.cnblogs.com/student-note/p/12514745.html
Copyright © 2011-2022 走看看