在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 }运行结果
完整代码
1 using System;
2 using System.Linq;
3 using System.Reflection;
4 using System.Reflection.Emit;
5
6 namespace EmitCreateDynamicProxy
7 {
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 var command = Proxy.Of<Command>();
13 command.Execute();
14
15 Console.WriteLine("Hi, Dennis, great, we got the interceptor works.");
16 Console.ReadLine();
17 }
18 }
19
20 public class Command
21 {
22 public virtual void Execute()
23 {
24 Console.WriteLine("Command executing...");
25 Console.WriteLine("Hello Kitty!");
26 Console.WriteLine("Command executed.");
27 }
28 }
29
30 public class Interceptor
31 {
32 public object Invoke(object @object, string @method, object[] parameters)
33 {
34 Console.WriteLine(
35 string.Format("Interceptor does something before invoke [{0}]...", @method));
36
37 var retObj = @object.GetType().GetMethod(@method).Invoke(@object, parameters);
38
39 Console.WriteLine(
40 string.Format("Interceptor does something after invoke [{0}]...", @method));
41
42 return retObj;
43 }
44 }
45
46 public class Proxy
47 {
48 public static T Of<T>() where T : class, new()
49 {
50 string nameOfAssembly = typeof(T).Name + "ProxyAssembly";
51 string nameOfModule = typeof(T).Name + "ProxyModule";
52 string nameOfType = typeof(T).Name + "Proxy";
53
54 var assemblyName = new AssemblyName(nameOfAssembly);
55 var assembly = AppDomain.CurrentDomain
56 .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
57 var moduleBuilder = assembly.DefineDynamicModule(nameOfModule);
58
59 var typeBuilder = moduleBuilder.DefineType(
60 nameOfType, TypeAttributes.Public, typeof(T));
61
62 InjectInterceptor<T>(typeBuilder);
63
64 var t = typeBuilder.CreateType();
65
66 return Activator.CreateInstance(t) as T;
67 }
68
69 private static void InjectInterceptor<T>(TypeBuilder typeBuilder)
70 {
71 // ---- define fields ----
72
73 var fieldInterceptor = typeBuilder.DefineField(
74 "_interceptor", typeof(Interceptor), FieldAttributes.Private);
75
76 // ---- define costructors ----
77
78 var constructorBuilder = typeBuilder.DefineConstructor(
79 MethodAttributes.Public, CallingConventions.Standard, null);
80 var ilOfCtor = constructorBuilder.GetILGenerator();
81
82 ilOfCtor.Emit(OpCodes.Ldarg_0);
83 ilOfCtor.Emit(OpCodes.Newobj, typeof(Interceptor).GetConstructor(new Type[0]));
84 ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor);
85 ilOfCtor.Emit(OpCodes.Ret);
86
87 // ---- define methods ----
88
89 var methodsOfType = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.Instance);
90
91 for (var i = 0; i < methodsOfType.Length; i++)
92 {
93 var method = methodsOfType[i];
94 var methodParameterTypes =
95 method.GetParameters().Select(p => p.ParameterType).ToArray();
96
97 var methodBuilder = typeBuilder.DefineMethod(
98 method.Name,
99 MethodAttributes.Public | MethodAttributes.Virtual,
100 CallingConventions.Standard,
101 method.ReturnType,
102 methodParameterTypes);
103
104 var ilOfMethod = methodBuilder.GetILGenerator();
105 ilOfMethod.Emit(OpCodes.Ldarg_0);
106 ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor);
107
108 // create instance of T
109 ilOfMethod.Emit(OpCodes.Newobj, typeof(T).GetConstructor(new Type[0]));
110 ilOfMethod.Emit(OpCodes.Ldstr, method.Name);
111
112 // build the method parameters
113 if (methodParameterTypes == null)
114 {
115 ilOfMethod.Emit(OpCodes.Ldnull);
116 }
117 else
118 {
119 var parameters = ilOfMethod.DeclareLocal(typeof(object[]));
120 ilOfMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length);
121 ilOfMethod.Emit(OpCodes.Newarr, typeof(object));
122 ilOfMethod.Emit(OpCodes.Stloc, parameters);
123
124 for (var j = 0; j < methodParameterTypes.Length; j++)
125 {
126 ilOfMethod.Emit(OpCodes.Ldloc, parameters);
127 ilOfMethod.Emit(OpCodes.Ldc_I4, j);
128 ilOfMethod.Emit(OpCodes.Ldarg, j + 1);
129 ilOfMethod.Emit(OpCodes.Stelem_Ref);
130 }
131 ilOfMethod.Emit(OpCodes.Ldloc, parameters);
132 }
133
134 // call Invoke() method of Interceptor
135 ilOfMethod.Emit(OpCodes.Callvirt, typeof(Interceptor).GetMethod("Invoke"));
136
137 // pop the stack if return void
138 if (method.ReturnType == typeof(void))
139 {
140 ilOfMethod.Emit(OpCodes.Pop);
141 }
142
143 // complete
144 ilOfMethod.Emit(OpCodes.Ret);
145 }
146 }
147 }
148 }
點擊查看更多內容
為 TA 點贊
評論
評論
共同學習,寫下你的評論
評論加載中...
作者其他優質文章
正在加載中
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
