.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<ICanLog>();

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

肯定是有的!我們可以通過映射(mapping)進代碼里面。但如果在代碼里面進行映射,還是要進行編譯。那如果把映射關系放到 XML 文件里面,就不用重新編譯啦。在開發中,是體會不了這種爽的。舉個栗子:

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

OK,這里通過 XML 配置文件進行映射的功能,換個概念 -- IoC(Inversion of Control,控制反轉),什么意思?

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 提供的就是構造函數的注入方式。但注入還可以是屬性的注入。屬性注入就像是選擇性依賴關系,而構造函數的注入就像是強制性依賴關系。(屬性注入跟構造函數可以下次單獨進行討論)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM