C#使用Emit构造拦截器动态代理类 在AOP编程概念介绍中,常见的示例为拦截对象,并在对象的某方法执行前和执行后分别记录日志。
而最常用的拦截方式是使用动态代理类,用其封装一个日志拦截器,当方法被执行时进行日志记录。
日志拦截器类 复制代码 1publicclassInterceptor 2{ 3publicobjectInvoke(object@object,string@method,object[]parameters) 4{ 5Console.WriteLine( 6string.Format("Interceptordoessomethingbeforeinvoke[{0}]...",@method)); 7 8varretObj=@object.GetType().GetMethod(@method).Invoke(@object,parameters); 9 10Console.WriteLine( 11string.Format("Interceptordoessomethingafterinvoke[{0}]...",@method)); 12 13returnretObj; 14} 15} 复制代码 被拦截对象类 假设我们有一个Command类,包含一个方法Execute用于执行一些工作。
复制代码 1publicclassCommand 2{ 3publicvirtualvoidExecute() 4{ 5Console.WriteLine("Commandexecuting..."); 6Console.WriteLine("HelloKitty!"); 7Console.WriteLine("Commandexecuted."); 8} 9} 复制代码 我们需要在Execute方法执行前和执行后分别记录日志。
动态代理类 复制代码 1publicclassProxy 2{ 3publicstaticTOf()whereT:class,new() 4{ 5stringnameOfAssembly=typeof(T).Name+"ProxyAssembly"; 6stringnameOfModule=typeof(T).Name+"ProxyModule"; 7stringnameOfType=typeof(T).Name+"Proxy"; 8 9varassemblyName=newAssemblyName(nameOfAssembly); 10varassembly=AppDomain.CurrentDomain 11.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.Run); 12varmoduleBuilder=assembly.DefineDynamicModule(nameOfModule); 13 14vartypeBuilder=moduleBuilder.DefineType( 15nameOfType,TypeAttributes.Public,typeof(T)); 16 17InjectInterceptor(typeBuilder); 18 19vart=typeBuilder.CreateType(); 20 21returnActivator.CreateInstance(t)asT; 22} 23 24privatestaticvoidInjectInterceptor(TypeBuildertypeBuilder) 25{ 26//----definefields---- 27 28varfieldInterceptor=typeBuilder.DefineField( 29"_interceptor",typeof(Interceptor),FieldAttributes.Private); 30 31//----definecostructors---- 32 33varconstructorBuilder=typeBuilder.DefineConstructor( 34MethodAttributes.Public,CallingConventions.Standard,null); 35varilOfCtor=constructorBuilder.GetILGenerator(); 36 37ilOfCtor.Emit(OpCodes.Ldarg_0); 38ilOfCtor.Emit(OpCodes.Newobj,typeof(Interceptor).GetConstructor(newType[0])); 39ilOfCtor.Emit(OpCodes.Stfld,fieldInterceptor); 40ilOfCtor.Emit(OpCodes.Ret); 41 42//----definemethods---- 43 44varmethodsOfType=typeof(T).GetMethods(BindingFlags.Public|BindingFlags.Instance); 45 46for(vari=0;i47{ 48varmethod=methodsOfType[i]; 49varmethodParameterTypes= 50method.GetParameters().Select(p=>p.ParameterType).ToArray(); 51 52varmethodBuilder=typeBuilder.DefineMethod( 53methodwww.wang027.com.Name, 54MethodAttributes.Public|MethodAttributes.Virtual, 55CallingConventions.Standard, 56method.ReturnType, 57methodParameterTypes); 58 59varilOfMethod=methodBuilder.GetILGenerator(); 60ilOfMethod.Emit(OpCodes.Ldarg_0); 61ilOfMethod.Emit(OpCodes.Ldfld,fieldInterceptor); 62 63//createinstanceofT 64ilOfMethod.Emit(OpCodes.Newobj,typeof(T).GetConstructor(newType[0])); 65ilOfMethod.Emit(OpCodes.Ldstr,method.Name); 66 67//buildthemethodparameters 68if(methodParameterTypes==null) 69{ 70ilOfMethod.Emit(OpCodes.Ldnull); 71} 72else 73{ 74varparameters=ilOfMethod.DeclareLocal(typeof(object[])); 75ilOfMethod.Emit(OpCodes.Ldc_I4,methodParameterTypes.Length); 76ilOfMethod.Emit(OpCodes.Newarr,typeof(object)); 77ilOfMethod.Emit(OpCodes.Stloc,parameters); 78 79for(varj=0;j80{ 81ilOfMethod.Emit(OpCodes.Ldloc,parameters); 82ilOfMethod.Emit(OpCodes.Ldc_I4,j); 83ilOfMethod.Emit(OpCodes.Ldarg,j+1); 84ilOfMethod.Emit(OpCodes.Stelem_Ref); 85} 86ilOfMethod.Emit(OpCodes.Ldloc,parameters); 87} 88 89//callInvoke()methodofInterceptor 90ilOfMethod.Emit(OpCodes.Callvirt,typeof(Interceptor).GetMethod("Invoke")); 91 92//popthestackifreturnvoid 93if(method.ReturnType==typeof(void)) 94{ 95ilOfMethod.Emit(OpCodes.Pop); 96} 97 98//complete 99ilOfMethod.Emit(OpCodes.Ret); 100} 101} 102} 复制代码 使用动态代理类 复制代码 1classProgram 2{ 3staticvoidMain(string[]args) 4{ 5varcommand=Proxy.Of(); 6command.Execute(); 7 8Console.WriteLine("Hi,Dennis,great,wegottheinterceptorworks."); 9Console.ReadLine(); 10} 11} |
|