溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

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

發(fā)布時間:2020-07-05 22:48:21 來源:網(wǎng)絡(luò) 閱讀:773 作者:鄒君安 欄目:網(wǎng)絡(luò)安全


AOP介紹

面向切面編程(Aspect Oriented Programming,英文縮寫為AOP),通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)。

AOP是OOP的延續(xù),是軟件開發(fā)中的一個熱點.

常用于:

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, nullnull);

    }

}

執(zhí)行

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有動態(tài)代理和靜態(tài)IL織入.

本節(jié)主要介紹動態(tài)代理方式,靜態(tài)可參考PostSharp.

 

Castle Core

原理:本質(zhì)是創(chuàng)建繼承原來類的代理類.重寫虛方法實現(xiàn)AOP功能.

 

只需引用:

Install-Package Castle.Core

(在Castle的2.5以上版本,已經(jīng)將 Castle.DynamicProxy2.dll 里有內(nèi)容,集成到 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}方法,參數(shù)值:{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("攔截器調(diào)用方法前,方法名是:{0}。", invocation.Method.Name);

    }

    protected override void PerformProceed(IInvocation invocation)

    {

        Console.WriteLine("攔截器開始調(diào)用方法,方法名是:{0}。", invocation.Method.Name);

        var attrs = invocation.MethodInvocationTarget.Attributes.HasFlag(MethodAttributes.Abstract);//過濾abstract方法

        if (!attrs)

        {

            base.PerformProceed(invocation);//此處會調(diào)用真正的方法 invocation.Proceed();

        }

    }

    protected override void PostProceed(IInvocation invocation)

    {

        Console.WriteLine("攔截器調(diào)用方法后,方法名是:{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();  //實例化【攔截器】 

    //使用【代理類生成器】創(chuàng)建Person對象,而不是使用new關(guān)鍵字來實例化 

    var person = generator.CreateClassProxy<Person>(interceptor);

    Console.WriteLine("當(dāng)前類型:{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

通過特性標(biāo)簽綁定

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!");

     }

 }

 

啟用攔截器執(zhí)行

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默認(rèn)提供了三種攔截器:TransparentProxyInterceptor、InterfaceInterceptor、VirtualMethodInterceptor。

TransparentProxyInterceptor:代理實現(xiàn)基于.NET Remoting技術(shù),它可攔截對象的所有函數(shù)。缺點是被攔截類型必須派生于MarshalByRefObject。

InterfaceInterceptor:只能對一個接口做攔截,好處時只要目標(biāo)類型實現(xiàn)了指定接口就可以攔截。

VirtualMethodInterceptor:對virtual函數(shù)進行攔截。缺點是如果被攔截類型沒有virtual函數(shù)則無法攔截,這個時候如果類型實現(xiàn)了某個特定接口可以改用

 

Install-Package Unity.Interception

1

2

3

4

5

6

7

8

9

10

11

12

13

public class MyHandler : ICallHandler

{

    public int Order { getset; }//這是ICallHandler的成員,表示執(zhí)行順序

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)

    {

        Console.WriteLine("方法執(zhí)行前");

        //這之前插入方法執(zhí)行前的處理

        var retvalue = getNext()(input, getNext);//在這里執(zhí)行方法

        //這之后插入方法執(zhí)行后的處理

        Console.WriteLine("方法執(zhí)行后");

        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();

}


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI