C# Aspect-Oriented Programming(AOP) 利用多種模式實現動態代理

來源:互聯網
上載者:User

標籤:rri   lin   自訂   名稱   class   size   維護   操作   可操作性   

什麼是AOP(Aspect-Oriented Programming)?

AOP允許開發人員動態地修改靜態OO模型,構造出一個能夠不斷增長以滿足新增需求的系統,就象現實世界中的對象會在其生命週期中不斷改變自身,應用程式也可以在發展中擁有新的功能。

AOP利用一種稱為“橫切”的技術,剖解開封裝的對象內部,並將那些影響了多個類的行為封裝到一個可重用模組,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,

卻為業務模組所共同調用的邏輯或責任,例如交易處理、日誌管理、許可權控制等,封裝起來,便於減少系統的重複代碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。

 

AOP技術本質

 

AOP(Aspect-Oriented Programming,面向方面編程),可以說是OOP(Object-Oriented Programing,物件導向編程)的補充和完善。OOP引入封裝、繼承和多態性等概念來建立一種對象階層,

用以類比公用行為的一個集合。當我們需要為分散的對象引入公用行為的時候,OOP則顯得無能為力。也就是說,OOP允許你定義從上到下的關係,但並不適合定義從左至右的關係。例如日誌功能。

日誌代碼往往水平地散布在所有對象層次中,而與它所散布到的對象的核心功能毫無關係。對於其他類型的代碼,如安全性、異常處理和透明的持久性也是如此。這種散布在各處的無關的代碼被稱為

橫切(cross-cutting)代碼,在OOP設計中,它導致了大量代碼的重複,而不利於各個模組的重用。

 

而AOP技術則恰恰相反,它利用一種稱為“橫切”的技術,剖解開封裝的對象內部,並將那些影響了多個類的公用行為封裝到一個可重用模組,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,

就是將那些與業務無關,卻為業務模組所共同調用的邏輯或責任封裝起來,便於減少系統的重複代碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。AOP代表的是一個橫向的關係,

如果說“對象”是一個空心的圓柱體,其中封裝的是對象的屬性和行為;那麼面向方面編程的方法,就彷彿一把利刃,將這些空心圓柱體剖開,以獲得其內部的訊息。而剖開的切面,也就是所謂的“方面”了。

然後它又以巧奪天功的妙手將這些剖開的切面複原,不留痕迹。

 

使用“橫切”技術,AOP把軟體系統分為兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。橫切關注點的一個特點是,他們經常發生在核心關注點的多處,

而各處都基本相似。比如許可權認證、日誌、交易處理。Aop 的作用在於分離系統中的各種關注點,將核心關注點和橫切關注點分離開來。正如Avanade公司的進階方案構架師Adam Magee所說,

AOP的核心思想就是“將應用程式中的商業邏輯同對其提供支援的泛型服務進行分離。”

實現AOP的技術,主要分為兩大類:一是採用動態代理技術,利用截取訊息的方式,對該訊息進行裝飾,以取代原有對象行為的執行;二是採用靜態織入的方式,引入特定的文法建立“方面”,從而使得編譯器可以在編譯期間織入有

關“方面”的代碼。然而殊途同歸,實現AOP的技術特性卻是相同的,分別為:

1、join point(連接點):是程式執行中的一個精確執行點,例如類中的一個方法。它是一個抽象的概念,在實現AOP時,並不需要去定義一個join point。

2、point cut(切入點):本質上是一個捕獲連接點的結構。在AOP中,可以定義一個point cut,來捕獲相關方法的調用。

3、advice(通知):是point cut的執行代碼,是執行“方面”的具體邏輯。

4、aspect(方面):point cut和advice結合起來就是aspect,它類似於OOP中定義的一個類,但它代表的更多是對象間橫向的關係。

5、introduce(引入):為對象引入附加的方法或屬性,從而達到修改對象結構的目的。有的AOP工具又將其稱為mixin。

上述的技術特性組成了基本的AOP技術,大多數AOP工具均實現了這些技術。它們也可以是研究AOP技術的基本術語。

 

1.C# 手動實現實現靜態代理 <AOP在方法前後增加自訂的方法>

假設一個情境, 當使用者在系統登入, 現在需要在登入前分別做一個版本校正, 和使用者登入緩衝處理... <利用裝飾者模式實現靜態代理實現登入前後增加自訂方法>

/// <summary>    /// 裝飾器模式實現靜態代理    /// AOP在方法前後增加自訂的方法    /// </summary>    public class Decorator    {        public static void Show()        {            User user = new User() { Name = "Eleven", Password = "123123123123" };            IUserProcessor processor = new UserProcessor();            processor = new UserProcessorDecorator(processor);            processor.RegUser(user);        }        public interface IUserProcessor        {            void RegUser(User user);        }        public class UserProcessor : IUserProcessor        {            public void RegUser(User user)            {                Console.WriteLine("使用者登入, Name:{0},PassWord:{1}", user.Name, user.Password);            }        }        /// <summary>        /// 裝飾器的模式去提供一個AOP功能        /// </summary>        public class UserProcessorDecorator : IUserProcessor        {            private IUserProcessor UserProcessor { get; set; }            public UserProcessorDecorator(IUserProcessor userprocessor)            {                UserProcessor = userprocessor;            }            public void RegUser(User user)            {                PreProceed(user);                this.UserProcessor.RegUser(user);                PostProceed(user);            }            public void PreProceed(User user)            {                Console.WriteLine("檢查軟體版本資訊...");            }            public void PostProceed(User user)            {                Console.WriteLine("儲存本機快取...");            }        }    }

如果沒有使用AOP, 上面的需求我們要怎麼去實現, 唯一的方法就是在執行方法的前後分別新增版本資訊檢查, 和本機快取處理。

public static void Show()        {            User user = new User() { Name = "Eleven", Password = "123123123123" };            IUserProcessor processor = new UserProcessor();            Console.WriteLine("檢查軟體版本資訊...");            processor.RegUser(user);            Console.WriteLine("儲存本地登入緩衝...");                        }

2.使用Castle\DynamicProxy 實現動態代理

using Castle.DynamicProxy;//Castle.Core    

/// <summary> /// 使用Castle\DynamicProxy 實現動態代理 /// </summary> public class CastleProxy { public static void Show() { User user = new User() { Name = "Eleven", Password = "123123123123" }; ProxyGenerator generator = new ProxyGenerator(); MyInterceptor interceptor = new MyInterceptor(); UserProcessor userprocessor = generator.CreateClassProxy<UserProcessor>(interceptor); userprocessor.RegUser(user); } public class MyInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { PreProceed(invocation); invocation.Proceed(); PostProceed(invocation); } public void PreProceed(IInvocation invocation) { Console.WriteLine("檢查軟體版本資訊"); } public void PostProceed(IInvocation invocation) { Console.WriteLine("儲存本地登入緩衝"); } } public interface IUserProcessor { void RegUser(User user); } public class UserProcessor : IUserProcessor { public virtual void RegUser(User user) { Console.WriteLine("使用者登入。Name:{0},PassWord:{1}", user.Name, user.Password); } } }

3. 使用.Net Remoting/RealProxy 實現動態代理

/// <summary>    /// 使用.Net Remoting/RealProxy 實現動態代理    /// </summary>    public class Proxy    {        public static void Show()        {            User user = new User() { Name = "Eleven", Password = "123123123123" };            UserProcessor userprocessor = TransparentProxy.Create<UserProcessor>();            userprocessor.RegUser(user);        }        public class MyRealProxy<T> : RealProxy        {            private T tTarget;            public MyRealProxy(T target)                : base(typeof(T))            {                this.tTarget = target;            }            public override IMessage Invoke(IMessage msg)            {                PreProceede(msg);                IMethodCallMessage callMessage = (IMethodCallMessage)msg;                object returnValue = callMessage.MethodBase.Invoke(this.tTarget, callMessage.Args);                PostProceede(msg);                return new ReturnMessage(returnValue, new object[0], 0, null, callMessage);            }            public void PreProceede(IMessage msg)            {                Console.WriteLine("檢查軟體版本資訊");            }            public void PostProceede(IMessage msg)            {                Console.WriteLine("儲存本地登入緩衝");            }        }        //TransparentProxy        public static class TransparentProxy        {            public static T Create<T>()            {                T instance = Activator.CreateInstance<T>();                MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);                T transparentProxy = (T)realProxy.GetTransparentProxy();                return transparentProxy;            }        }        public interface IUserProcessor        {            void RegUser(User user);        }        public class UserProcessor : MarshalByRefObject, IUserProcessor        {            public void RegUser(User user)            {                Console.WriteLine("使用者登入。使用者名稱稱{0} Password{1}", user.Name, user.Password);            }        }    }

 

C# Aspect-Oriented Programming(AOP) 利用多種模式實現動態代理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.