Aspect# 語言目的是免去在 XML 語法上滾來滾去之苦,提供一個乾淨的方式配置、識別和書寫你的切面配置。
內容索引
1. 基礎定義
2. Import 匯入
3. 全域性攔截機
4. 全域性 Mixin 混入
5. 切面 aspect
6. 包含 include
7. 切入點 pointcut
8. 通知 advice
1. 基礎定義
在使用 Aspect# 語言時務必遵循一些規則,首要的規則是順序。因此你的宣告務必遵循以下順序:
[Import 匯入][Interceptor 全域性攔截機對映]
[Mixin 全域性混入對映]
Aspects 切面定義
2. Import 匯入
匯入區域幫助你保持一個乾淨的程式碼環境,並幫助 Aspect 語言解釋類的宣告。
import 名稱空間名稱 [in 程式集名稱]例如:
import System.Collections in Systemimport AspectSharp.Core
3. 全域性攔截機
當你有一個攔截機,準備運用到多個切面,甚或運用到多個切入點的時候,你可以把它定義到全域性攔截機區域:
interceptors ["鍵名1" : 攔截機類A ;
"鍵名2" : 攔截機類B
]
例如
interceptors ["logger" : DigitalGravity.Interceptors.Logger in DigitalGravity.XProject
]
這是沒有匯入名稱空間的對映宣告。
import DigitalGravity.Interceptors in DigitalGravity.XProjectinterceptors [
"logger" : Logger
]
這是已經匯入名稱空間的對映宣告。
當你完成這些後,就可以在一個切面定義中通過關鍵字 advice 根據『鍵名』來引用它們:
aspect Test for MyClasspointcut method(*)
advice("key")
end
pointcut property(*)
advice("key2")
end
end
4. 全域性混入
同樣的理由,我們也需要一個全域性混入區域:
mixins ["鍵名1" : 混入類A ;
"鍵名2" : 混入類B
]
例如
mixins ["security" : DigitalGravity.Mixins.SecurityMixin in DigitalGravity.XProject
]
這是沒有匯入名稱空間的對映宣告。
Import DigitalGravity.Mixins in DigitalGravity.XProjectmixins [
"security" : SecurityMixin
]
這是已經匯入名稱空間的對映宣告。
當你完成這些後,就可以在一個切面定義中通過 include 關鍵字並根據『鍵名』來引用它們:
aspect Test for MyClassinclude("security")
end
注意,mixin 混入使用的是 include 引用,而攔截機使用的是 advice 引用。
5. 切面 aspect
一個切面區域用來定義哪些混入 mixin 和哪些切入點 pointcut 將被應用到某個或某些類:
aspect 切面名稱 for 類名[匯入]
[切入點]
end
例如
aspect MyAspect for Customerend
這是為特定某個類(Customer)宣告切面的示例。
aspect MyAspect for [ My.Namespace.Classes excludes(Customer,Author) ]end
這是為特定某個名稱空間(My.Namespace.Classes)中的類宣告切面的示例,但把 Customer, Author 兩個類排除在外。
aspect MyAspect for [ assignableFrom(Customer) ]end
這是為繼承或實現自 Customer 父類或介面的所有類宣告切面的示例。
aspect MyAspect for [ customMatcher(自定義匹配器類名) ]end
這是使用了自定義匹配器宣告切面的示例。
當你在一個例項中呼叫了 AspectEngine.Wrap() 方法,基本上 Aspect# 會嘗試找出與這個例項匹配的切面。如果匹配了多個切面,將從這個集合中建立一個新的切面並作為這個切面的定義。(???)
如果你需要在匹配切面時採用更特別的語義,你可以通過 customMatcher 關鍵字(示例如上)提供你自己的切面匹配器。你的類必須實現 IClassMatcher 介面,並編寫邏輯使得當這個例項符合你希望的切面要求時返回真值 true 。
6. 引用 include
你可以在一個切面定義中使用一個或多個 include 引用已經定義了的混入 mixin 。
include("鍵名")這是宣告瞭全域性混入對映後的引用方式。
include 類名 in 程式集這是沒有宣告全域性混入對映,需要從程式集中引入的引用方式。
例如
include DigitalGravity.Mixins.Security in DigitalGravity.XProject
include System.Collections.ArrayList in System
end
7. 切入點 pointcut
切入點的目的是為執行通知而定義的一套有效的表示式,
pointcut [目標][方法簽名]advice(類名)
advice("鍵名")
end
『目標』可能是:method、property、propertyread 或 propertywrite。
如果需要你也可以像這樣把它們組合起來:
pointcut method|property(*)endpointcut method|propertyread(*)
endpointcut propertywrite(*)
end
但是使用 property|propertywrite 是毫無意義的,你也會因此得到一個錯誤。
『方法簽名』可以簡單如一個 (*) 表示所有,或 (System.IList Create(int,*)) 表示所有返回型別為 System.IList 且至少第一個引數型別是 int 的名為 Create 的方法。請注意,在這裡,返回值型別和引數型別必須使用完整的類名稱,正如 System.IList 而不能只是 IList 。
正規表示式不被完全支援。實際上,你可以只使用 .* 來匹配一個名字的剩餘部分,像 (Str.* Create(int, string)) 將匹配所有帶有兩個引數(第一個引數是 int 型別,第二個引數是 string 型別)並返回一個名稱字首是 Str (例如 String, Strange, Stripissimo)的型別的名為 Create 的方法。
例如
// 所有名為 Name 的讀屬性和寫屬性pointcut property(* Name)
end
// 所有如同 C*****Name 一樣的讀屬性和寫屬性,譬如 CustomerName
pointcut property(string C.*Name)
end
// 返回型別為 void 、沒有引數、名為 Perform 的方法
pointcut method(void Perform)
end
// 第一個引數是 String 型別而我們不關心其他引數的名為 Perform 的方法
pointcut method(void Perform(string, *))
end
8. 通知 advice
通知 advice 是一些與切入點有關的程式碼片段。Aspect# 只支援方法攔截機的通知。
advice("鍵名")advice(攔截機類名)
advice(攔截機類名 in 程式集名稱)
請注意,我們對攔截機使用延遲載入,並且在每次 Wrap() 中一個攔截機只會有一個例項。換言之,多個代理之間不會共享攔截機。
例如
aspect MyAspect for Customerpointcut method(*)
advice(LogInvocationInterceptor)
end
endaspect MyAspect for Customer
pointcut method(*)
advice(Namespace.MyLogger in MyAssembly)
end
end