轉自:https://www.cnblogs.com/neverc/p/5241466.html
AOP介紹
面向切面編程(Aspect Oriented Programming,英文縮寫為AOP),通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。
AOP是OOP的延續,是軟件開發中的一個熱點.
常用于:
Authentication?
Caching
Lazy loading
Transactions
?
AOP基本原理
普通類
1 2 3 4 5 6 7 8 9 | class ?Person : MarshalByRefObject { ???? public ?string ?Say() ???? { ???????? const ?string ?str =? "Person's say is called" ; ???????? Console.WriteLine(str); ???????? return ?str; ???? } } |
代理類
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public ?class ?Proxy<T> : RealProxy? where ?T :? new () { ???? private ?object ?_obj; ???? public ?Proxy( object ?obj) ???????? :? base ( typeof (T)) ???? { ???????? _obj = obj; ???? } ???? public ?override ?IMessage Invoke(IMessage msg) ???? { ???????? Console.WriteLine( "{0}:Invoke前" , DateTime.Now); ???????? var ?ret = ((IMethodCallMessage)msg).MethodBase.Invoke(_obj,? null ); ???????? Console.WriteLine( "{0}:Invoke后" , DateTime.Now); ???????? return ?new ?ReturnMessage(ret,? null , 0,? null ,? null ); ???? } } |
執行
1 2 3 4 5 6 7 8 9 10 | static ?void ?Main( string [] args) { ???? var ?per =? new ?Proxy<Person>( new ?Person()).GetTransparentProxy()? as ?Person; ???? if ?(per !=? null ) ???? { ???????? var ?str = per.Say(); ???????? Console.WriteLine( "返回值:" ?+ str); ???? } ???? Console.ReadKey(); } |
?
AOP框架
AOP有動態代理和靜態IL織入.
本節主要介紹動態代理方式,靜態可參考PostSharp.
?
Castle Core
原理:本質是創建繼承原來類的代理類.重寫虛方法實現AOP功能.
?
只需引用:
Install-Package Castle.Core
(在Castle的2.5以上版本,已經將 Castle.DynamicProxy2.dll 里有內容,集成到 Castle.Core.dll 中。)
?
Simple Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public ?abstract ?class ?Person { ???? public ?virtual ?void ?SayHello() ???? { ???????? Console.WriteLine( "我是{0}方法" ,? "SayHello" ); ???? } ???? public ?virtual ?void ?SayName( string ?name) ???? { ???????? Console.WriteLine( "我是{0}方法,參數值:{1}" ,? "SayName" , name); ???? } ???? public ?abstract ?void ?AbstactSayOther(); ???? public ?void ?SayOther() ???? { ???????? Console.WriteLine( "我是{0}方法" ,? "SayOther" ); ???? } } |
?
interceptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public ?class ?SimpleInterceptor : StandardInterceptor { ???? protected ?override ?void ?PreProceed(IInvocation invocation) ???? { ???????? Console.WriteLine( "攔截器調用方法前,方法名是:{0}。" , invocation.Method.Name); ???? } ???? protected ?override ?void ?PerformProceed(IInvocation invocation) ???? { ???????? Console.WriteLine( "攔截器開始調用方法,方法名是:{0}。" , invocation.Method.Name); ???????? var ?attrs = invocation.MethodInvocationTarget.Attributes.HasFlag(MethodAttributes.Abstract); //過濾abstract方法 ???????? if ?(!attrs) ???????? { ???????????? base .PerformProceed(invocation); //此處會調用真正的方法 invocation.Proceed(); ???????? } ???? } ???? protected ?override ?void ?PostProceed(IInvocation invocation) ???? { ???????? Console.WriteLine( "攔截器調用方法后,方法名是:{0}。" , invocation.Method.Name); ???? } } |
?
Main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | static ?void ?Main( string [] args) { ???? var ?generator =? new ?ProxyGenerator();??????? //實例化【代理類生成器】? ???? var ?interceptor =? new ?SimpleInterceptor();?? //實例化【攔截器】? ???? //使用【代理類生成器】創建Person對象,而不是使用new關鍵字來實例化? ???? var ?person = generator.CreateClassProxy<Person>(interceptor); ???? Console.WriteLine( "當前類型:{0},父類型:{1}" , person.GetType(), person.GetType().BaseType); ???? Console.WriteLine(); ???? person.SayHello(); //攔截 ???? Console.WriteLine(); ???? person.SayName( "Never、C" ); //攔截 ???? Console.WriteLine(); ???? person.SayOther(); //普通方法,無法攔截???? ???? person.AbstactSayOther(); //抽象方法,可以攔截???? ???? Console.ReadLine(); } |
?
Castle Windsor
特性式AOP
1 2 3 4 5 6 7 8 9 10 11 12 13 | public ?interface ?IPerson { ???? void ?Say(); } [Interceptor( typeof (LogInterceptor))] public ?class ?Person : IPerson { ???? public ?void ?Say() ???? { ???????? Console.WriteLine( "Person's Say Method is called!" ); ???? } } |
?
1 2 3 4 5 6 7 8 9 | public ?class ?LogInterceptor : IInterceptor { ???? public ?void ?Intercept(IInvocation invocation) ???? { ???????? Console.WriteLine( "{0}:攔截{1}方法{2}前," , DateTime.Now.ToString( "O" ), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name); ???????? invocation.Proceed(); ???????? Console.WriteLine( "{0}:攔截{1}方法{2}后," , DateTime.Now.ToString( "O" ), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name); ???? } } |
?
1 2 3 4 5 6 7 8 9 10 11 | static ?void ?Main( string [] args) { ???? using ?( var ?container =? new ?WindsorContainer()) ???? { ???????? container.Register(Component.For<Person, IPerson>()); ???????? container.Register(Component.For<LogInterceptor, IInterceptor>()); ???????? var ?person = container.Resolve<IPerson>(); ???????? person.Say(); ???? } ???? Console.ReadKey(); } |
非侵入式AOP
1 2 3 4 5 6 7 8 9 10 11 12 | public ?interface ?IPerson { ???? void ?Say(); } public ?class ?Person : IPerson { ???? public ?void ?Say() ???? { ???????? Console.WriteLine( "Person's Say Method is called!" ); ???? } } |
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | internal ?static ?class ?LogInterceptorRegistrar { ???? public ?static ?void ?Initialize(WindsorContainer container) ???? { ???????? container.Kernel.ComponentRegistered += Kernel_ComponentRegistered; ???? } ???? private ?static ?void ?Kernel_ComponentRegistered( string ?key, IHandler handler) ???? { ???????? handler.ComponentModel.Interceptors.Add( new ?InterceptorReference( typeof (LogInterceptor))); ???? } } public ?class ?LogInterceptor : IInterceptor { ???? public ?void ?Intercept(IInvocation invocation) ???? { ???????? Console.WriteLine( "{0}:攔截{1}方法{2}前," , DateTime.Now.ToString( "O" ), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name); ???????? invocation.Proceed(); ???????? Console.WriteLine( "{0}:攔截{1}方法{2}后," , DateTime.Now.ToString( "O" ), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name); ???? } } |
?
1 2 3 4 5 6 7 8 9 10 11 12 | static ?void ?Main( string [] args) { ???? using ?( var ?container =? new ?WindsorContainer()) ???? { ???????? container.Register(Component.For<IInterceptor, LogInterceptor>()); //先注入攔截器 ???????? LogInterceptorRegistrar.Initialize(container); ???????? container.Register(Component.For<IPerson, Person>()); ???????? var ?person = container.Resolve<IPerson>(); ???????? person.Say(); ???? } ???? Console.ReadKey(); } |
?
Autofac
Install-Package Autofac.Aop
通過特性標簽綁定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class ?LogInterceptor : IInterceptor ? { ????? public ?void ?Intercept(IInvocation invocation) ????? { ????????? Console.WriteLine( "{0}:攔截{1}方法{2}前," , DateTime.Now.ToString( "O" ), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name); ????????? invocation.Proceed(); ????????? Console.WriteLine( "{0}:攔截{1}方法{2}后," , DateTime.Now.ToString( "O" ), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name); ????? } ? } ? public ?interface ?IPerson ? { ????? void ?Say(); ? } ? [Intercept( typeof (LogInterceptor))] ? public ?class ?Person : IPerson ? { ????? public ?void ?Say() ????? { ????????? Console.WriteLine( "Person's Say Method is called!" ); ????? } ? } |
?
啟用攔截器執行
1 2 3 4 5 6 7 8 9 10 11 | static ?void ?Main( string [] args) { ???? var ?builder =? new ?ContainerBuilder(); ???? builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors(); ???? builder.RegisterType<LogInterceptor>(); ???? using ?( var ?container = builder.Build()) ???? { ???????? container.Resolve<IPerson>().Say(); ???? } ???? Console.ReadLine(); } |
?
或采用非侵入性方法(去掉class上的特性仍可以)
1 2 3 4 5 6 7 8 9 10 11 | static ?void ?Main( string [] args) { ???? var ?builder =? new ?ContainerBuilder(); ???? builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors().InterceptedBy( typeof (LogInterceptor)); ???? builder.RegisterType<LogInterceptor>(); ???? using ?( var ?container = builder.Build()) ???? { ???????? container.Resolve<IPerson>().Say(); ???? } ???? Console.ReadLine(); } |
?
Unity
Unity默認提供了三種攔截器:TransparentProxyInterceptor、InterfaceInterceptor、VirtualMethodInterceptor。
TransparentProxyInterceptor:代理實現基于.NET Remoting技術,它可攔截對象的所有函數。缺點是被攔截類型必須派生于MarshalByRefObject。
InterfaceInterceptor:只能對一個接口做攔截,好處時只要目標類型實現了指定接口就可以攔截。
VirtualMethodInterceptor:對virtual函數進行攔截。缺點是如果被攔截類型沒有virtual函數則無法攔截,這個時候如果類型實現了某個特定接口可以改用
?
Install-Package Unity.Interception
1 2 3 4 5 6 7 8 9 10 11 12 13 | public ?class ?MyHandler : ICallHandler { ???? public ?int ?Order {? get ;? set ; } //這是ICallHandler的成員,表示執行順序 ???? public ?IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) ???? { ???????? Console.WriteLine( "方法執行前" ); ???????? //這之前插入方法執行前的處理 ???????? var ?retvalue = getNext()(input, getNext); //在這里執行方法 ???????? //這之后插入方法執行后的處理 ???????? Console.WriteLine( "方法執行后" ); ???????? return ?retvalue; ???? } } |
?
1 2 3 4 5 6 7 | public ?class ?MyHandlerAttribute : HandlerAttribute { ???? public ?override ?ICallHandler CreateHandler(IUnityContainer container) ???? { ???????? return ?new ?MyHandler(); //返回MyHandler ???? } } |
?
1 2 3 4 5 6 7 8 9 10 11 12 13 | public ?interface ?IPerson { ???? void ?Say(); } [MyHandler] public ?class ?Person : IPerson { ???? public ?virtual ?void ?Say() ???? { ???????? Console.WriteLine( "Person's Say Method is called!" ); ???? } } |
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | static ?void ?Main( string [] args) { ???? using ?( var ?container =? new ?UnityContainer()) ???? { ???????? container.AddNewExtension<Interception>(); ???????? //1.TransparentProxyInterceptor ???????? //container.Configure<Interception>().SetInterceptorFor<IPerson>(new TransparentProxyInterceptor()); ???????? //2.InterfaceInterceptor (使用1,2,3均可,這種侵入性最小) ???????? container.Configure<Interception>().SetInterceptorFor<IPerson>( new ?InterfaceInterceptor()); ???????? //3.VirtualMethodInterceptor ???????? //container.Configure<Interception>().SetInterceptorFor<Person>(new VirtualMethodInterceptor()); ???????? container.RegisterType<IPerson, Person>(); ???????? container.Resolve<IPerson>().Say(); ???? } ???? Console.ReadKey(); } |