动态方法与动态代理(下篇)

动态代理:

  代理模式和装饰模式的区别:

  装饰模式:在不改变接口的前提下,动态扩展对象的功能

      代理模式:在不改变接口的前提下,控制对象的访问

      代理类和被代理对象是has-a关系,一般没有is-a关系,除非代理类直接继承被代理类,重写被代理类的方法

动态代理是指通过动态代码技术在运行时生成具体类的代理,目的是在执行具体类的操作之前或之后运行特定的逻辑

动态代理既可以代理类也可以代理接口,代理类时,被代理的类不能为Sealed,并且其中属性和方法都必须为Virtual,而代理接口时则无约束条件

 •Demo:动态生成接口的代理

 

View Code
  1    public   interface  ICalculate
  2      {
  3           void  Add( int  a,  int  b);
  4      }
  5 
  6       public   class  A : ICalculate
  7      {
  8           #region  ICalculate 成员
  9 
 10           public   void  Add( int  a,  int  b)
 11          {
 12              Console.WriteLine(a  +  b);
 13          }
 14 
 15           #endregion
 16      }
 17 
 18       public   class  B : ICalculate
 19      {
 20          ICalculate _inst;
 21 
 22           public  B(ICalculate o)
 23          {
 24              _inst  =  o;
 25          }
 26 
 27           #region  ICalculate 成员
 28 
 29           public   void  Add( int  a,  int  b)
 30          {
 31              Console.WriteLine( " Before... " );
 32              _inst.Add(a, b);
 33              Console.WriteLine( " After... " );
 34          }
 35 
 36           #endregion
 37      }
 38 
 39       class  Program
 40      {
 41           static   void  Main( string [] args)
 42          {
 43              Type proxyType; // 代理类型
 44 
 45               #region  Emit Class
 46 
 47              AssemblyName assemblyName  =   new  AssemblyName( " DynamicAssemblyExample " );
 48              AssemblyBuilder assemblyBuilder  =  AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
 49              ModuleBuilder moduleBuilder  =  assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name  +   " .dll " );
 50 
 51              TypeBuilder typeBuilder  =  moduleBuilder.DefineType( " DynamicAssemblyExample.Calculate " , TypeAttributes.Public  |  TypeAttributes.Class
 52                  ,  typeof ( object ),  new  Type[] {  typeof (ICalculate) });
 53 
 54              FieldBuilder instanceField  =  typeBuilder.DefineField( " _instance " typeof (ICalculate), FieldAttributes.Private);
 55 
 56              ConstructorBuilder constructorBuilder  =  typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard,  new  Type[] {  typeof (ICalculate) });
 57 
 58              ILGenerator ilGenConstructor  =  constructorBuilder.GetILGenerator();
 59              ilGenConstructor.Emit(OpCodes.Ldarg_0);
 60              ilGenConstructor.Emit(OpCodes.Call,  typeof ( object ).GetConstructor(Type.EmptyTypes));  // base.ctor()
 61              ilGenConstructor.Emit(OpCodes.Ldarg_0);
 62              ilGenConstructor.Emit(OpCodes.Ldarg_1);
 63              ilGenConstructor.Emit(OpCodes.Stfld, instanceField);
 64              ilGenConstructor.Emit(OpCodes.Ret);
 65 
 66              MethodInfo addMethodInfo  =   typeof (ICalculate).GetMethod( " Add " );
 67 
 68              MethodAttributes methodAttr  =  addMethodInfo.Attributes  &   ~ (MethodAttributes.Abstract);
 69 
 70              List < Type >  paramTypes  =   new  List < Type > ();
 71 
 72               foreach  (ParameterInfo pInfo  in  addMethodInfo.GetParameters())
 73              {
 74                  paramTypes.Add(pInfo.ParameterType);
 75              }
 76 
 77              MethodBuilder addMethod  =  typeBuilder.DefineMethod(addMethodInfo.Name, methodAttr,
 78                  CallingConventions.Standard, addMethodInfo.ReturnType, paramTypes.ToArray());
 79 
 80               // writeline call
 81              MethodInfo writeLineMethod  =   typeof (Console).GetMethod( " WriteLine " new  Type[] {  typeof ( string ) });
 82 
 83              ILGenerator ilGenAddMethod  =  addMethod.GetILGenerator();
 84 
 85 
 86              ilGenAddMethod.Emit(OpCodes.Ldstr,  " Before... " );
 87              ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
 88 
 89               // 每个实例方法都默认包含一个隐藏的参数,即第0个参数,它对应的是this指针,但静态方法没有隐藏的第0个参数
 90              ilGenAddMethod.Emit(OpCodes.Ldarg_0);
 91              ilGenAddMethod.Emit(OpCodes.Ldfld, instanceField);
 92 
 93              
 94              ilGenAddMethod.Emit(OpCodes.Ldarg_1); // a
 95              ilGenAddMethod.Emit(OpCodes.Ldarg_2); // b
 96              ilGenAddMethod.Emit(OpCodes.Callvirt,  typeof (ICalculate).GetMethod( " Add " )); // a+b
 97 
 98              ilGenAddMethod.Emit(OpCodes.Ldstr,  " After... " );
 99              ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
100 
101               /*
102               * Console.WriteLine(this.GetType().FullName);
103                */
104              ilGenAddMethod.DeclareLocal( typeof ( int ));
105              ilGenAddMethod.Emit(OpCodes.Ldarg_0);
106              ilGenAddMethod.Emit(OpCodes.Callvirt,  typeof ( object ).GetMethod( " GetType " ));
107              ilGenAddMethod.Emit(OpCodes.Callvirt,  typeof (Type).GetMethod( " get_FullName " ));
108              ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
109 
110 
111              ilGenAddMethod.Emit(OpCodes.Ret);
112 
113              proxyType  =  typeBuilder.CreateType();
114 
115              assemblyBuilder.Save( " DynamicAssemblyExample.dll " );
116               #endregion
117 
118              ICalculate proxyImp  =  (ICalculate)proxyType.GetConstructor( new  Type[] {  typeof (ICalculate) })
119                  .Invoke( new   object [] {  new  A() });
120 
121              proxyImp.Add( 10 20 );
122          }
123      }

 AOP的概念

  •Aspect Oriented Programming
  •AOP是OOP的延续,意思是面向切面编程
  •切面是指整体中的某个行为(功能)部分
  •目标:将与主逻辑无紧密关系的行为,从业务逻辑代码中分离出来
  •优点:当改变某个行为时,不会影响到业务逻辑,并且使代码进一步解耦
  •常用于日志记录,性能统计,安全控制,事务处理,异常处理等等
AOP的工作原理 
•AOP的关键是拦截正常的方法调用,即将需要额外附加的功能透明的“织入( Weave)”到这些方法中
•所谓“织入”简单的讲就是指将附件功能和目标的原有功能融合在一起,AOP像一台织布机,将两者天衣无缝的编织起来,织入是透明的
•在.Net中,AOP的织入方式有两种:

   静态织入:在编译阶段将附加逻辑写入代码中

   动态织入:在运行阶段将附加逻辑写入代码中 

  •静态织入:一般都需要扩展编译器的功能,优点是代码执行的效率高,缺点是实现者需要对虚拟机有很深的了解,而且修改代码之后都需要重新编译,目前,最著名的产品是:PostSharp
  •动态织入:不需要扩展编译器的功能,优点是在运行时自动生成代码,缺点是执行效率不高,需要额外的开销,目前,运用动态织入方法的产品较多,Castle.DynamicProxy是其中的经典之一

   动态织入的实现技术就是动态代理,由于静态织入存在局限性,一般来说,AOP框架实现方式首选动态织入,因此,AOP可以看作是动态代理发展的产物

 •Demo:AOP实践Castle.DynamicProxy

这是一个轻量级的,能为一个或多个接口或具体类创建动态代理的类库,或者称之为AOP类库内部机制是使用反射发出动态织入
拦截器( Interceptor)是其中的重要概念,用于截获方法的调用,增加新的逻辑,自定义拦截器必须实现IInterceptor接口或者继承内置的标准拦截器类StandardInterceptor拦截器对方法和属性都有效

典型应用:
   参数检验
   延迟加载(Lazy Loading)
典型代表:
   NHibernate

 

View Code
 1    class  Program
 2      {
 3           static   void  Main( string [] args)
 4          {
 5              DemoClassInterceptorTest.DoTest();
 6 
 7               // DemoInterfaceInterceptorTest.DoTest();
 8          }
 9      }
10  public   interface  IDemoInterface
11      {
12           void  Add( int  a,  int  b);
13      }
14 
15       public   class  DemoInterfaceClass : IDemoInterface
16      {
17           #region  DemoInterface 成员
18 
19           public   void  Add( int  a,  int  b)
20          {
21              Console.WriteLine(a  +  b);
22          }
23 
24           #endregion
25      }
26 
27       public   class  DemoInterfaceInterceptor : StandardInterceptor
28      {
29           protected   override   void  PreProceed(IInvocation invocation)
30          {
31              Console.WriteLine( " PreProceed:{0} " , invocation.Method.ToString());
32          }
33 
34           protected   override   void  PostProceed(IInvocation invocation)
35          {
36              Console.WriteLine( " PostProceed:{0} " , invocation.Method.ToString());
37          }
38 
39           protected   override   void  PerformProceed(IInvocation invocation)
40          {
41               base .PerformProceed(invocation);
42          }
43      }
44 
45       public   class  DemoInterfaceInterceptorTest
46      {
47           public   static   void  DoTest()
48          {
49              DemoInterfaceClass realObj  =   new  DemoInterfaceClass();
50 
51              DemoInterfaceInterceptor interceptor  =   new  DemoInterfaceInterceptor();
52 
53              ProxyGenerator generator  =   new  ProxyGenerator();
54              IDemoInterface proxy = generator.CreateInterfaceProxyWithTargetInterface < IDemoInterface > (realObj, interceptor);
55              proxy.Add( 10 50 );
56          }
57      }

 

View Code
 1    public   class  DemoClass
 2      {
 3 
 4           string  _text;
 5           public   virtual   string  Text
 6          {
 7               get
 8              {
 9                   return  _text;
10              }
11               set
12              {
13                  _text  =  value;
14              }
15          }
16 
17           public   virtual   void  Add( int  a,  int  b)
18          {
19              Console.WriteLine(a  +  b);
20          }
21      }
22 
23       class  DemoClassInterceptor : IInterceptor
24      {
25           #region  IInterceptor 成员
26 
27           ///   <summary>
28           ///  Intercepts the specified invocation.
29           ///   </summary>
30           ///   <param name="invocation"> The invocation. </param>
31           public   void  Intercept(IInvocation invocation)
32          {
33              PreProceed(invocation);
34              invocation.Proceed();
35              PostProceed(invocation);
36          }
37 
38           #endregion
39 
40           public   void  PreProceed(IInvocation invocation)
41          {
42              Console.WriteLine( " PreProceed 1 代理了:{0} " , invocation.Method.ToString());
43          }
44 
45           public   void  PostProceed(IInvocation invocation)
46          {
47              Console.WriteLine( " PostProceed 1 代理了:{0} " , invocation.Method.ToString());
48          }
49      }
50 
51       class  DemoClassInterceptor2 : IInterceptor
52      {
53           #region  IInterceptor 成员
54 
55           ///   <summary>
56           ///  Intercepts the specified invocation.
57           ///   </summary>
58           ///   <param name="invocation"> The invocation. </param>
59           public   void  Intercept(IInvocation invocation)
60          {
61              PreProceed(invocation);
62              invocation.Proceed();
63              PostProceed(invocation);
64          }
65 
66           #endregion
67 
68           public   void  PreProceed(IInvocation invocation)
69          {
70              Console.WriteLine( " PreProceed 2 代理了:{0} " , invocation.Method.ToString());
71          }
72 
73           public   void  PostProceed(IInvocation invocation)
74          {
75              Console.WriteLine( " PostProceed 2 代理了:{0} " , invocation.Method.ToString());
76          }
77      }
78 
79       class  DemoClassInterceptorTest
80      {
81           public   static   void  DoTest()
82          {
83              ProxyGenerator generator  =   new  ProxyGenerator();
84              DemoClassInterceptor interceptor  =   new  DemoClassInterceptor();
85              DemoClassInterceptor2 interceptor2  =   new  DemoClassInterceptor2();
86              DemoClass obj  =  generator.CreateClassProxy < DemoClass > (interceptor, interceptor2);
87              obj.Text  =   " test " ;
88              obj.Add( 10 20 );
89          }
90      }

 

你可能感兴趣的:(动态代理)