在AOP编程概念介绍中,常见的示例为拦截对象,并在对象的某方法执行前和执行后分别记录日志。
而最常用的拦截方式是使用动态代理类,用其封装一个日志拦截器,当方法被执行时进行日志记录。
日志拦截器类
1 public class Interceptor 2 { 3 public object Invoke(object @object, string @method, object[] parameters) 4 { 5 Console.WriteLine( 6 string.Format("Interceptor does something before invoke [{0}]...", @method)); 7 8 var retObj = @object.GetType().GetMethod(@method).Invoke(@object, parameters); 9 10 Console.WriteLine( 11 string.Format("Interceptor does something after invoke [{0}]...", @method)); 12 13 return retObj; 14 } 15 }
被拦截对象类
假设我们有一个Command类,包含一个方法Execute用于执行一些工作。
1 public class Command 2 { 3 public virtual void Execute() 4 { 5 Console.WriteLine("Command executing..."); 6 Console.WriteLine("Hello Kitty!"); 7 Console.WriteLine("Command executed."); 8 } 9 }
我们需要在Execute方法执行前和执行后分别记录日志。
动态代理类
1 public class Proxy 2 { 3 public static T Of<T>() where T : class, new() 4 { 5 string nameOfAssembly = typeof(T).Name + "ProxyAssembly"; 6 string nameOfModule = typeof(T).Name + "ProxyModule"; 7 string nameOfType = typeof(T).Name + "Proxy"; 8 9 var assemblyName = new AssemblyName(nameOfAssembly); 10 var assembly = AppDomain.CurrentDomain 11 .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 12 var moduleBuilder = assembly.DefineDynamicModule(nameOfModule); 13 14 var typeBuilder = moduleBuilder.DefineType( 15 nameOfType, TypeAttributes.Public, typeof(T)); 16 17 InjectInterceptor<T>(typeBuilder); 18 19 var t = typeBuilder.CreateType(); 20 21 return Activator.CreateInstance(t) as T; 22 } 23 24 private static void InjectInterceptor<T>(TypeBuilder typeBuilder) 25 { 26 // ---- define fields ---- 27 28 var fieldInterceptor = typeBuilder.DefineField( 29 "_interceptor", typeof(Interceptor), FieldAttributes.Private); 30 31 // ---- define costructors ---- 32 33 var constructorBuilder = typeBuilder.DefineConstructor( 34 MethodAttributes.Public, CallingConventions.Standard, null); 35 var ilOfCtor = constructorBuilder.GetILGenerator(); 36 37 ilOfCtor.Emit(OpCodes.Ldarg_0); 38 ilOfCtor.Emit(OpCodes.Newobj, typeof(Interceptor).GetConstructor(new Type[0])); 39 ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor); 40 ilOfCtor.Emit(OpCodes.Ret); 41 42 // ---- define methods ---- 43 44 var methodsOfType = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.Instance); 45 46 for (var i = 0; i < methodsOfType.Length; i++) 47 { 48 var method = methodsOfType[i]; 49 var methodParameterTypes = 50 method.GetParameters().Select(p => p.ParameterType).ToArray(); 51 52 var methodBuilder = typeBuilder.DefineMethod( 53 method.Name, 54 MethodAttributes.Public | MethodAttributes.Virtual, 55 CallingConventions.Standard, 56 method.ReturnType, 57 methodParameterTypes); 58 59 var ilOfMethod = methodBuilder.GetILGenerator(); 60 ilOfMethod.Emit(OpCodes.Ldarg_0); 61 ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor); 62 63 // create instance of T 64 ilOfMethod.Emit(OpCodes.Newobj, typeof(T).GetConstructor(new Type[0])); 65 ilOfMethod.Emit(OpCodes.Ldstr, method.Name); 66 67 // build the method parameters 68 if (methodParameterTypes == null) 69 { 70 ilOfMethod.Emit(OpCodes.Ldnull); 71 } 72 else 73 { 74 var parameters = ilOfMethod.DeclareLocal(typeof(object[])); 75 ilOfMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length); 76 ilOfMethod.Emit(OpCodes.Newarr, typeof(object)); 77 ilOfMethod.Emit(OpCodes.Stloc, parameters); 78 79 for (var j = 0; j < methodParameterTypes.Length; j++) 80 { 81 ilOfMethod.Emit(OpCodes.Ldloc, parameters); 82 ilOfMethod.Emit(OpCodes.Ldc_I4, j); 83 ilOfMethod.Emit(OpCodes.Ldarg, j + 1); 84 ilOfMethod.Emit(OpCodes.Stelem_Ref); 85 } 86 ilOfMethod.Emit(OpCodes.Ldloc, parameters); 87 } 88 89 // call Invoke() method of Interceptor 90 ilOfMethod.Emit(OpCodes.Callvirt, typeof(Interceptor).GetMethod("Invoke")); 91 92 // pop the stack if return void 93 if (method.ReturnType == typeof(void)) 94 { 95 ilOfMethod.Emit(OpCodes.Pop); 96 } 97 98 // complete 99 ilOfMethod.Emit(OpCodes.Ret); 100 } 101 } 102 }
使用动态代理类
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var command = Proxy.Of<Command>(); 6 command.Execute(); 7 8 Console.WriteLine("Hi, Dennis, great, we got the interceptor works."); 9 Console.ReadLine(); 10 } 11 }
运行结果
完整代码
View Code