AOP原理解析及Castle、Autofac、Unity框架使用

转自: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();
}

转载于:https://www.cnblogs.com/chenyishi/p/9676011.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值