动态代理:
代理模式和装饰模式的区别:
装饰模式:在不改变接口的前提下,动态扩展对象的功能
代理模式:在不改变接口的前提下,控制对象的访问
代理类和被代理对象是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 }