• C# 实现 Aop [Emit动态生成代理类方式]


      1     using System.Reflection;
      2     using System.Reflection.Emit;
      3     public static class DefaultProxyBuilder
      4     {
      5         private static readonly Type VoidType = Type.GetType("System.Void"); //函数返回 void类型
      6 
      7         public static T CreateProxy<T>()
      8         {
      9             Type classType = typeof(T);
     10 
     11             string name = classType.Namespace + ".Aop"; //新的命名空间
     12             string fileName = name + ".dll";
     13 
     14 
     15             var assemblyName = new AssemblyName(name);         
     16             var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.RunAndSave);
     17             var moduleBuilder = assemblyBuilder.DefineDynamicModule(name, fileName);//构建命名空间
     18             var aopType = BulidType(classType, moduleBuilder);
     19 
     20             assemblyBuilder.Save(fileName);
     21             return (T)Activator.CreateInstance(aopType);
     22         }
     23 
     24         private static Type BulidType(Type classType, ModuleBuilder moduleBuilder)
     25         {
     26             string className = classType.Name + "_Proxy";
     27 
     28             //定义类型
     29             var typeBuilder = moduleBuilder.DefineType(className,
     30                                                        TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class,
     31                                                        classType);//定义一个新类,继承classType
     32             //定义字段 _inspector 声明一个私有且只读的变量
     33             var inspectorFieldBuilder = typeBuilder.DefineField("_inspector", typeof(IInterceptor),
     34                                                                 FieldAttributes.Private | FieldAttributes.InitOnly);
     35             //构造函数 
     36             BuildCtor(classType, inspectorFieldBuilder, typeBuilder);
     37 
     38             //构造方法
     39             BuildMethod(classType, inspectorFieldBuilder, typeBuilder);
     40             Type aopType = typeBuilder.CreateType();
     41             return aopType;
     42         }
     43 
     44         private static void BuildMethod(Type classType, FieldBuilder inspectorFieldBuilder, TypeBuilder typeBuilder)
     45         {
     46             var methodInfos = classType.GetMethods();//获取 原类型
     47             foreach (var methodInfo in methodInfos)// 获取 虚函数 或 抽象函数
     48             {
     49                 if (!methodInfo.IsVirtual && !methodInfo.IsAbstract)
     50                     continue;
     51                 if (methodInfo.Name == "ToString")
     52                     continue;
     53                 if (methodInfo.Name == "GetHashCode")
     54                     continue;
     55                 if (methodInfo.Name == "Equals")
     56                     continue;
     57 
     58                 var parameterInfos = methodInfo.GetParameters();
     59                 var parameterTypes = parameterInfos.Select(p => p.ParameterType).ToArray();
     60                 var parameterLength = parameterTypes.Length;
     61                 var hasResult = methodInfo.ReturnType != VoidType;
     62 
     63                 var methodBuilder = typeBuilder.DefineMethod(methodInfo.Name,
     64                                                              MethodAttributes.Public | MethodAttributes.Final |
     65                                                              MethodAttributes.Virtual
     66                                                              , methodInfo.ReturnType
     67                                                              , parameterTypes);
     68 
     69                 var il = methodBuilder.GetILGenerator();
     70 
     71                 //局部变量 声明
     72                 il.DeclareLocal(typeof(object)); //correlationState (emit 标签从0 开始:loc_0,loc_1,loc_2)
     73                 il.DeclareLocal(typeof(object)); //result
     74                 il.DeclareLocal(typeof(object[])); //parameters
     75 
     76                 #region BeforeCall
     77                 //BeforeCall(string operationName, object[] inputs);
     78                 il.Emit(OpCodes.Ldarg_0);
     79 
     80                 il.Emit(OpCodes.Ldfld, inspectorFieldBuilder);//获取字段_inspector
     81                 il.Emit(OpCodes.Ldstr, methodInfo.Name);//参数operationName
     82 
     83                 if (parameterLength == 0)//判断方法参数长度
     84                 {
     85                     il.Emit(OpCodes.Ldnull);//null -> 参数 inputs
     86                 }
     87                 else
     88                 {
     89                     //创建new object[parameterLength];
     90                     il.Emit(OpCodes.Ldc_I4, parameterLength);
     91                     il.Emit(OpCodes.Newarr, typeof(Object));
     92                     il.Emit(OpCodes.Stloc_2);//压入局部变量2 parameters
     93 
     94                     for (int i = 0, j = 1; i < parameterLength; i++, j++)
     95                     {
     96                         //object[i] = arg[j]
     97                         il.Emit(OpCodes.Ldloc_2);
     98                         il.Emit(OpCodes.Ldc_I4, 0);
     99                         il.Emit(OpCodes.Ldarg, j);
    100                         if (parameterTypes[i].IsValueType)
    101                             il.Emit(OpCodes.Box, parameterTypes[i]);//对值类型装箱
    102                         il.Emit(OpCodes.Stelem_Ref);
    103                     }
    104                     il.Emit(OpCodes.Ldloc_2);//取出局部变量2 parameters-> 参数 inputs
    105                 }
    106 
    107                 il.Emit(OpCodes.Callvirt, typeof(IInterceptor).GetMethod("BeforeCall"));//调用BeforeCall
    108                 il.Emit(OpCodes.Stloc_0);//建返回压入局部变量0 correlationState
    109                 #endregion
    110 
    111                 #region base.Call
    112                 //Call methodInfo
    113                 il.Emit(OpCodes.Ldarg_0); // arg_0: 
    114                 //获取参数表
    115                 for (int i = 1, length = parameterLength + 1; i < length; i++)
    116                 {
    117                     il.Emit(OpCodes.Ldarg_S, i);
    118                 }
    119                 il.Emit(OpCodes.Call, methodInfo);
    120                 //将返回值压入 局部变量1result void就压入null
    121                 if (!hasResult)
    122                     il.Emit(OpCodes.Ldnull);
    123                 else if (methodInfo.ReturnType.IsValueType)
    124                     il.Emit(OpCodes.Box, methodInfo.ReturnType);//对值类型装箱
    125                 il.Emit(OpCodes.Stloc_1); //返回值 保存到 result
    126                 #endregion
    127 
    128                 #region AfterCall
    129                 //AfterCall(string operationName, object returnValue, object correlationState);
    130                 il.Emit(OpCodes.Ldarg_0);
    131                 il.Emit(OpCodes.Ldfld, inspectorFieldBuilder);//获取字段_inspector
    132                 il.Emit(OpCodes.Ldstr, methodInfo.Name);//参数 operationName
    133                 il.Emit(OpCodes.Ldloc_1);//局部变量1 result
    134                 il.Emit(OpCodes.Ldloc_0);// 局部变量0 correlationState
    135                 il.Emit(OpCodes.Callvirt, typeof(IInterceptor).GetMethod("AfterCall"));
    136                 #endregion
    137 
    138                 #region result
    139                 //result 返回结果: void类型 直接返回函数,否则...
    140                 if (!hasResult)
    141                 {
    142                     il.Emit(OpCodes.Ret);
    143                     return;
    144                 }
    145                 il.Emit(OpCodes.Ldloc_1);//非void取出局部变量1 result
    146                 if (methodInfo.ReturnType.IsValueType)
    147                     il.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType);//对值类型拆箱
    148                 il.Emit(OpCodes.Ret);
    149                 #endregion
    150             }
    151         }
    152 
    153         private static void BuildCtor(Type classType, FieldBuilder inspectorFieldBuilder, TypeBuilder typeBuilder)
    154         {
    155             {  //定义 代理类的 构造器
    156                 var ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis,
    157                                                                 Type.EmptyTypes);
    158                 var il = ctorBuilder.GetILGenerator();
    159 
    160                 il.Emit(OpCodes.Ldarg_0);
    161                 il.Emit(OpCodes.Call, classType.GetConstructor(Type.EmptyTypes));//调用base的默认ctor
    162                 il.Emit(OpCodes.Ldarg_0);
    163                 //将typeof(classType)压入计算堆
    164                 il.Emit(OpCodes.Ldtoken, classType);
    165                 il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) }));
    166                 //调用DefaultInterceptorFactory.Create(type)
    167                 il.Emit(OpCodes.Call, typeof(DefaultInterceptorFactory).GetMethod("Create", new[] { typeof(Type) }));
    168                 //将结果保存到字段_inspector
    169                 il.Emit(OpCodes.Stfld, inspectorFieldBuilder);
    170                 il.Emit(OpCodes.Ret);
    171             }
    172         }
    173     }

    注:http://www.189works.com/article-43203-1.html

  • 相关阅读:
    mysql 账户管理
    关于数据库设计的思考(三)
    学习 ThinkPHP 框架笔记
    学习 Ext Js 所感
    mysql 一个较特殊的问题:You can't specify target table 'wms_cabinet_form' for update in FROM clause
    关于数据库设计的思考(二)
    flash、flex 项目开发学习时的笔记
    web.config 中SessionState的配置
    公农历转换
    使用Microsoft Web Application Stress Tool对web进行压力测试
  • 原文地址:https://www.cnblogs.com/AspDotNetMVC/p/2918289.html
Copyright © 2020-2023  润新知