【 Autofac打標簽模式】開源DI框架擴展地址:
https://github.com/yuzd/Autofac.Annotation/wiki
前提條件
自己new一個對象不能實現攔截器功能,必須得從DI容器拿到的對象才能具備攔截器功能 可以參考 我寫的文章介紹
攔截器原理簡單介紹
用了Castle.Core組件 把你想要實現攔截器的目標類生成一個代理類。 然后織入攔截器,有2種方式
- class + 方法為virtual的方式
- 這種方式需要 從容器中是根據一個classType來獲取到目標實例
- interface + 方法重寫的方式
- 這種方式需要 從容器中是根據一個interfaceType來獲取到目標實例
攔截器開關
在你想要實現攔截的目標類上打上 【Aspect】標簽,如上面的解釋,Aspect標簽可以根據InterceptorType屬性值設定你是哪種方式的攔截器
| InterceptorType屬性 | 解釋 |
|---|---|
| Class | 使用class的虛方法模式 【默認方式】 |
| Interface | 使用接口模式 |
目的是打個標簽就能夠攔截目標方法
使得我們自定義的方法能夠
- 在指定的目標方法執行之前先執行(比如參數校驗)
- 或者在指定的目標方法執行之后執行(比如說檢驗返回值,或其他收尾工作)
- 或者環繞目標的方法,比如事務:TransactionScope或者記錄方法執行的時間
| 攔截器標簽 | 攔截器類型 | 使用說明 |
|---|---|---|
| AspectBeforeAttribute(抽象標簽類) | 前置攔截器 | 重寫Before方法 |
| AspectAfterAttribute(抽象標簽類) | 后置攔截器 | 重寫After方法 |
| AspectAroundAttribute(抽象標簽類) | 前置+后置攔截器 | 重寫Before和重寫After方法 |
| PointcutAttribute(抽象標簽類) | 環繞攔截器 | 重寫OnInvocation方法 |
攔截器的方法參數 AspectContext 屬性說明
| 名稱 | 說明 |
|---|---|
| ComponentContext | DI容器,可以從中取得你已注冊的實例 |
| InvocationContext | 執行上下文,例如被攔截的MethodInfo ,Name, Parameters,ReturnType等 |
| Exception | 異常信息,這個在前置攔截器是肯定為null,在后置攔截器中如果被攔截的方法出現了異常就能通過這個字段拿到異常信息 |
Exception說明
前置攔截器若拋了沒有被catch住的異常
- 如果有后置攔截器,可以在AspectContext的Exception字段獲取。
- 如果沒有后置攔截器則拋出
前置攔截器
- 首先要自己寫一個類繼承 前置攔截器AspectBeforeAttribute(抽象標簽類)
- 實現該抽象類的Before方法

1. 然后在被攔截方法的所在類上打上 【Aspect】標簽;
2. 被攔截方法上打上 【TestHelloBefor】標簽
3. 被攔截方法需要有 virtual 關鍵字

前置攔截器方法的執行順序為:先執行 TestHelloBefor的Before方法再執行你的Say方法
后置攔截器
- 首先要自己寫一個類繼承后置攔截器AspectAfterAttribute(抽象標簽類)
- 實現該抽象類的After方法

1. 然后在被攔截方法的所在類上打上 【Aspect】標簽;
2. 被攔截方法上打上 【TestHelloAfter】標簽
3. 被攔截方法需要有 virtual 關鍵字

后置攔截器方法的執行順序為:先執行你的SayAfter方法再執行 TestHelloAfter的After方法
前置+后置攔截器
- 首先要自己寫一個類繼承攔截器AspectAroundAttribute(抽象標簽類)
- 實現該抽象類的Before 和 After方法

1. 然后在被攔截方法的所在類上打上 【Aspect】標簽;
2. 被攔截方法上打上 【TestHelloArround】標簽
3. 被攔截方法需要有 virtual 關鍵字

方法的執行順序為:
- 先執行TestHelloArround的Before方法
- 然后執行你的SayArround方法
- 再執行 先執行TestHelloArround的After方法
環繞攔截器的前置+后置的另外一種方式(更靈活)
注意:OnInvocation方法除了AspectContext參數以外 還有一個 AspectDelegate _next 參數, 如果只有一個環繞攔截器的話,那么這個參數就是被攔截方法的本體, 如果有多個環繞攔截器的話,那么最后一個就是被攔截方法的本體。
- 首先要自己寫一個類繼承攔截器PointcutAttribute(抽象標簽類)
- 實現該抽象類的OnInvocation方法

1. 然后在被攔截方法的所在類上打上 【Aspect】標簽;
2. 被攔截方法上打上 【TransactionInterceptor】標簽
3. 被攔截方法需要有 virtual 關鍵字

方法的執行順序為:
- 先執行TransactionInterceptor的OnInvocation方法
- 然后TransactionInterceptor的OnInvocation方法里面執行的 await _next(aspectContext); 就會執行被攔截方法TestInterceptor;
如果有多個環繞攔截器的話,如下圖:


如上圖 代碼的執行順序為:

