配色: 字号:
C#使用Emit构造拦截器动态代理类
2016-09-14 | 阅:  转:  |  分享 
  
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}
献花(0)
+1
(本文系thedust79首藏)