歡迎光臨
每天分享高質量文章

.net core 註入機制與Autofac

本來是要先出註入機制再出 管道 的,哈哈哈……就是不按計劃來……

這裡扯扯題外話:為什麼要註入(DI,dependency-injection),而不用 new 物件?

可能我們都很清楚,new 物件所造成的影響就是耦合度太高,DI 就是用來解耦的。或者還可以說,DI 可以統一進行管理物件。

此話怎講呢?

這裡還要擴充套件一下,講一下介面(Interface)跟類(Class):

介面的話通常都像 IDisposable、IEnumerable 或者 ICollection 這些一樣以 ” I ” 開頭命名的;而類就是繼承並實現這些介面的(當然,類不一定要繼承),比如 List 或者 Map。他們兩個都有可能是 IEnumerable 的實現,因為他們都是多繼承的實現類。

所以說,通常我們的類都是依賴於其他的。比如說我們有個 Database 的類(當然日誌也行是吧),這個類主要是連線資料庫的。然後呢,這個類裡面,可能要做一下記錄,比如資料庫是否連線失敗呀,那麼就要在這個類裡面實體化另外一個 Logger 的類(平時的業務功能程式碼實現是不是都像這樣,哈哈哈)。那麼在 Database 類裡面實體化了 Logger 類,它們之間就存在了依賴關係(Database 依賴 Logger)。

    public class Database
    {
        public void DoSomething()
        {
            var logger = new Logger();
        }
    }

 

這程式碼沒毛病,但是如果突然有個需求說,我們的 Logger 不記錄在本地,我要透過 TCP/IP 記錄到另外一臺伺服器上。哈,我們是不是要改程式碼了……

如果我們不希望改動 Logger 裡面的程式碼,那麼我們就建立多一個 TcpLogger ,那麼是不是要在專案中將所有的或者需要使用到 TcpLogger 的 Logger 類進行替換。

 

    public class Database
    {
        public void DoSomething()
        {
            //var logger = new Logger();
            //替換成
            var logger = new TcpLogger();
        }
    }

 

這方法有點蠢吧,第一,沒啥意思;第二,很容易出現錯誤,改動的地方越多,就越容易出錯;第三,有點傻,重覆去做這些沒啥意思的事情,如果下次再換一種日誌方式,豈不是又要改一遍?!

理解設計樣式的人,很容易想到工廠樣式了吧,最常用的。(但,在講註入,扯到設計樣式,是不是跑題啦……)

設計樣式大概怎麼搞?

            ICanLog logger = new Logger();

熟悉啵,只要繼承 ICanLog 並且實現它,我們要什麼就 new 什麼。但這樣同樣是 new 實體的方式,也沒有做到,我要是換一種方式記錄日誌,還是要改程式碼呀。我就是忒不想改程式碼的。那就試試換一種:

 ICanLog logger = LoggerFactory.Create();
            //或者
    ICanLog logger = TypeFactory.Create();

這也超級熟悉的是不是。嗯,好像是要換什麼日誌方式,就去改型別工廠。改的少的,但是不是有可以不改程式碼的方式?

肯定是有的!我們可以透過對映(mapping)進程式碼裡面。但如果在程式碼裡面進行對映,還是要進行編譯。那如果把對映關係放到 XML 檔案裡面,就不用重新編譯啦。在開發中,是體會不了這種爽的。舉個慄子:

在生產環境中,如果某些原因,其中一個正在 Log 的功能運轉不了了,但是可以使用另外一種方式進行 Log,我們是不是更新一下 XML 配置檔案,替換一下就可以。(千萬別把改配置跟改程式碼混為一談,完全不同!本質區別!)

OK,這裡透過 XML 配置檔案進行對映的功能,換個概念 — IoC(Inversion of Control,控制反轉),什麼意思?

1
since you invert control over who decides what exact class to instantiate.

簡而言之,你控制你所要使用的實體,就是透過(配置)控制轉化你所要使用的類實體。

上面所說的其實跳過了很多很多,就是怎麼實現這種對映,程式碼中有怎麼決定使用哪一個實體呢?還是用日誌舉例:就是你本來就已經寫好了兩種日誌的樣式,你的配置只是確定你要使用哪一種日誌樣式而已,我們就可以當成這種是一種服務的定位器(就是確定我要使用的服務)。

現在的話,我們的程式碼已經不再是 Logger 類了,而且依賴於這個配置。

往回看一下日誌工廠或型別工廠的建立實體的過程,那麼註入的下一步就是獲得註入的實體,看程式碼:

        public Database(ICanLog logger) {

        }

見鬼啦,.net core 裡見得多了吧。當然,我們現在仍然是不知道到底怎麼註入的,註入的過程是怎麼樣的,但我們已經知道為什麼要用註入了。

終於要進入主題啦 — .net core 註入機制(.net core 提供了一個內建的服務容器 IServiceProvider,服務已在應用的 Startup.ConfigureServices 方法中註冊):引入了 Conforming Container  機制,包含了請求生命週期作用域, 服務註冊等等的統一概念。

 

看圖,看完就講完了,哈哈哈……其實圖中沒有將服務的生命週期畫出來,可以去《.net core 註入中的三種樣式:Singleton、Scoped 和 Transient》看服務容器 IServiceProvider 負責管理服務的過程。這裡補重覆碼字。

上圖中,我們看到一個容器,是 .net core 提供的一個容器,用來管理所註入的服務的。那麼既然有了一個容器,我們為什麼要在這篇裡面講 Autofac?Autofac 是什麼?

Autofac 是一款 Ioc 容器!

在 .net core 使用 Autofac ,我將它理解為容器的擴充套件與補充。(咦,可以來一篇 Autofac 的個人秀喲)

1、.net core 沒有能處理每個請求特定的作用域;

2、.net core 相比 Autofac,後者維護起來更方便(maintainability)、可讀性更強(readability),沒那麼容易混淆;

3、後續繼續總結!

.net core 與 Autofac 除了這些之外,它們之間只是選擇而已!

PS:.net core 提供的就是建構式的註入方式。但註入還可以是屬性的註入。屬性註入就像是選擇性依賴關係,而建構式的註入就像是強制性依賴關係。(屬性註入跟建構式可以下次單獨進行討論)

已同步到看一看
贊(0)

分享創造快樂