日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

C# 中使用面向切面编程(AOP)中实践代码整洁

發(fā)布時間:2023/12/4 C# 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# 中使用面向切面编程(AOP)中实践代码整洁 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1. 前言

最近在看《架構(gòu)整潔之道》一書,書中反復(fù)提到了面向?qū)ο缶幊痰?SOLID 原則(在作者的前一本書《代碼整潔之道》也是被大力闡釋),而面向切面編程(Aop)作為面向?qū)ο缶幊痰挠辛ρa(bǔ)充,對實(shí)踐整潔代碼更是如虎添翼。

除了整潔之道系列的影響外,本文還致敬、借鑒、補(bǔ)充了Aspect Oriented Programming (AOP) in C# with SOLID一文。

1. Aop 是什么?

在討論 Aop 之前,我們可以先看看一段很常見的代碼。

這是一段很典型的面向過程的代碼,我們可以看到有相同的異常處理邏輯,如果我們想要避免重復(fù)的代碼,我們至少可以把異常處理封裝一下:

代碼簡潔了很多,但是我們實(shí)際上是將真實(shí)的方法代碼與日志代碼糾纏在一起,違反了?單一責(zé)任原則?。有沒有一種可能,讓我們不需要在原來的代碼上顯式調(diào)用 TryCache 呢?

一個可能的答案是借助 AOP 來解決。使用 AOP,我們可以在不改變原來代碼的前提下,添加額外的單元功能(如異常處理,日志處理、重試機(jī)制等)。 AOP 可以把原來一大串的面向過程的代碼重構(gòu)成多個部分,聚焦于每一小部分,使我們的代碼?可讀性?和?維護(hù)性?更高,避免了?代碼重復(fù)和代碼糾纏?的問題。

2. 裝飾器實(shí)現(xiàn) AOP

C# 可以使用的 Aop 框架有很多,在我們談?wù)撍麄冎?#xff0c;我們可以先利用語言自帶的特性,實(shí)現(xiàn)基礎(chǔ)的 AOP 效果。 最簡單的形式莫過于?裝飾器模式?,它的雛形大致如下:

可以看到裝飾器只是在原來的對象上面擴(kuò)展,符合?開放封閉原則。我們在調(diào)用的時候,只需顯式創(chuàng)建裝飾實(shí)例對象。

var tryClient=new TryHandler<MyClient>(new MyClient());tryClient.GetOtherOne();

細(xì)心的讀者可能還會發(fā)現(xiàn),我們還可以在這個日志裝飾器上面再附加一個裝飾器,比如一個針對結(jié)果處理的裝飾器。

var resultClient=new ResultHandler<TryHandler<MyClient>>(tryClient);

但是這樣的調(diào)用方法還是不盡人意,想象如果某個對象有三四個裝飾器,那么我們創(chuàng)建實(shí)例的時候就需要多次傳遞。一個解決方法是?借助依賴注入 (DI)?,只需注冊一次服務(wù)類型,避免通過創(chuàng)建實(shí)例來獲取對象。另外,對于 .net core自帶的 DI 來說,更便捷的方法是借助開源類庫Scrutor?來注冊裝飾器對象。

services.Decorate<IMyClient, TryHandler<MyClient>>(); services.Decorate<IMyClient, ResultHandler<MyClient>>();

雖然解決了易用性,但是我們很快就發(fā)現(xiàn)了另一些不盡人意的地方,裝飾器模式只能適用于?特定的類型,約束是比較強(qiáng)的。如果我們希望我們示例中的裝飾器可以實(shí)現(xiàn)通用,就需要找別的方法了。

3. 動態(tài)代理實(shí)現(xiàn) Aop

動態(tài)代理是指運(yùn)行時生成,通過隱式重寫方法來附加額外的功能,而其中最流行的莫過于?Castle DynamicProxy了。

Castle DynamicProxy 的常規(guī)用法是繼承?IInterceptor?接口,通過實(shí)現(xiàn)?Intercept?方法來處理代理的邏輯。

在調(diào)用的時候,類似裝飾器一樣需要創(chuàng)建代理實(shí)例。

有很多開源項(xiàng)目在使用 Castle DynamicProxy,其穩(wěn)定性和可靠性是值得信賴的,更多的使用方法可以參照官方示例或者第三方開源項(xiàng)目的代碼。需要特別注意的是,Castle DynamicProxy 只能作用于接口或者虛方法,這是動態(tài)代理的特性(局限)。

除了 Castle DynamicProxy 外,?AspectCore也是一個不錯的選擇。AspectCore 的快速簡單應(yīng)用通過繼承?AbstractInterceptorAttribute?的 Attribute類來標(biāo)記并攔截代理對應(yīng)的接口或者虛方法(更詳細(xì)的用法可以參考?作者寫的使用方法)。

雖然易用性很好,但是要注意使用的場合,如果是在低層次(如基礎(chǔ)設(shè)施層、應(yīng)用入口層等)或者特定的應(yīng)用模塊內(nèi)使用,對整體架構(gòu)影響不大。如果是在高層次(邏輯層、核心層、領(lǐng)域?qū)拥?#xff09;使用,則會帶來不必要的依賴污染

所以并不是推薦使用這種 Attribute 攔截代理的方式,好在 AspectCore 的設(shè)計考慮到解耦的需要,可以在單獨(dú)配置代理攔截。

serviceCollection.ConfigureDynamicProxy(config =>{config.Interceptors.AddTyped<CustomInterceptorAttribute>(Predicates.ForMethod("ICustomService", "Call")); });

但是不管是 Castle DynamicProxy 還是 AspectCore 都只能作用與接口或者虛方法,這也是動態(tài)代理的局限(特性)。如果我們想要在不受限制地在非虛方法上實(shí)現(xiàn) AOP 的效果,就需要別的方法了。

4. 編譯時織入實(shí)現(xiàn) AOP

進(jìn)行 AOP 的另一種方法是通過編譯時織入,在編譯的程序集內(nèi)部的方法中添加額外的?IL 代碼,附加我們想要的功能。

PostSharp?是其中比較流行的一種,然而由于其商業(yè)化的性質(zhì),在這里不做過多介紹。開源方面,Fody?是其中的佼佼者。

Fody 在編譯時使用?Mono.Cecil?修改 . net 程序集的 IL 代碼。如果你沒有 IL 代碼方面的知識,可以直接使用基于 Fody 開發(fā)的插件。其中最流行的插件是Costura和?Virtuosity。Costura 將依賴項(xiàng)作為資源嵌入,實(shí)現(xiàn)多個 DLL 文件合并成一個 exe?的功能,而 Virtuosity 則是在構(gòu)建的時候?qū)⑺谐蓡T更改為?virtual?,重寫 ORM (如EF的導(dǎo)航屬性、NHibernate)、 Mock(RhinoMocks、NMock)以及前面提到的動態(tài)代理中需要?virtual?的地方為?virtual。

Fody 中的插件還有很多,除了 Costura 和 Virtuosity 之外,我個人還使用過?MethodDecorator,實(shí)現(xiàn)編譯時重寫類的方法或者構(gòu)造函數(shù)來實(shí)現(xiàn) AOP 的效果。

所有 Fody 的插件,首先都必須引入一個?FodyWeavers.xml?,并聲明使用的插件。

<?xml version="1.0" encoding="utf-8"?><!--FodyWeavers.xml--><Weavers><MethodDecorator /></Weavers>

不同的插件在后面的使用方法會有所不同,以 MethodDecorator 為例,我們需要新建一個特定格式的 Attribute 類,然后標(biāo)記在特定的類方法上面。

最后還需要一個?AssemblyInfo.cs?來配置哪些 Attribute 類產(chǎn)生作用。

//AssemblyInfo.csusing System; [module: FodyTest]

重新編譯生成,在輸出中還可以看到 Fody 的輸出。

既然我們可以在編譯時織入 IL 代碼,那么我們是不是可以提前生成我們想要的 AOP 效果,比如說借助代碼生成器。

5. 代碼生成器實(shí)現(xiàn) AOP 效果

T4是常見的文本生成框架,我們可以使用此工具在設(shè)計時生成代碼。前面我們提到過裝飾器模式有特異性的問題,只能針對特定類型實(shí)現(xiàn) AOP 效果,而借助代碼生成器,我們可以直接生成對應(yīng)的代碼模板,避免了重復(fù)的勞動。由于我個人對 T4 沒什么使用經(jīng)驗(yàn),有興趣的讀者可以參考Aspect Oriented Programming (AOP) in C# via T4一文。

除了 T4 之外,Roslyn?也是一個強(qiáng)有力的工具,已經(jīng)有人基于 Roslyn 實(shí)現(xiàn) AOP 的效果,將 Roslyn 封裝為?dotnet 全局工具?,針對特定的文件插入指定的代碼段,有興趣的讀者可以參考?AOP_With_Roslyn?的代碼示例。

結(jié)語

AOP 是我們?避免代碼重復(fù)?和?增強(qiáng)代碼可讀性?的有力工具,是我們編寫整潔代碼的有力保證,借助 C# 語言自身的特性和諸多強(qiáng)大的開源工具,使我們更專注于代碼功能。

原文地址:?https://www.cnblogs.com/chenug/p/9848852.html


.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com

總結(jié)

以上是生活随笔為你收集整理的C# 中使用面向切面编程(AOP)中实践代码整洁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。