使用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>;
            }
        }
    }

生成的代理对象如下:

   代码下载

原文地址:https://www.cnblogs.com/student-note/p/12514745.html