【AutoFac】依賴註入和控制反轉的使用

来源:https://www.cnblogs.com/yanbigfeg/archive/2018/10/28/9855960.html
-Advertisement-
Play Games

在開始之前首先解釋一下我認為的依賴註入和控制反轉的意思。(新手理解,哪裡說得不正確還請指正和見諒) 控制反轉:我們向IOC容器發出獲取一個對象實例的一個請求,IOC容器便把這個對象實例“註入”到我們的手中,在這個時候我們不是一個創建者,我們是以一個請求者的身份去請求容器給我們這個對象實例。我們所有的 ...


在開始之前首先解釋一下我認為的依賴註入和控制反轉的意思。(新手理解,哪裡說得不正確還請指正和見諒)

控制反轉:我們向IOC容器發出獲取一個對象實例的一個請求,IOC容器便把這個對象實例“註入”到我們的手中,在這個時候我們不是一個創建者,我們是以一個請求者的身份去請求容器給我們這個對象實例。我們所有的對象依賴於容器提供給你的資源,控制權落到了容器身上。在這裡的身份轉化或許就是控制反轉的核心吧。 

依賴註入:我們向容器發出請求以後,獲得這個對象實例的過程就叫依賴註入。也就是我們在使用對象前我們都需要先註入也就是這個意思吧。

 今天學習了下AutoFac依賴註入這個插件,然後還有以前用過的Unity這個插件簡單做個筆記整理。首先我分兩個部分記錄,第一部分一點有點的記錄今天學習的AutoFac這個插件,最後一部分直接補上以前使用Unity插件的代碼封裝不做詳細解釋。

AutoFac入門

還是放上官網給出的整合流程吧;

  • 按照 控制反轉 (IoC) 的思想構建你的應用.
  • 添加Autofac引用.
  • 在應用的 startup 處...
  • 創建 ContainerBuilder.
  • 註冊組件.
  • 創建容器,將其保存以備後續使用.
  • 應用執行階段...
  • 從容器中創建一個生命周期.
  • 在此生命周期作用域內解析組件實例.

創建簡單的例子

通過一個控制台簡單清晰的介紹瞭如何使用AutoFac這個插件。

創建項目

    創建一個控制台程式叫AutoFacDome。

    這裡就不做過多解釋了,大家都會創建哈哈。

引用Autofac

使用我vs強大的nuget來進行添加引用:

直接在搜索欄輸入Autofac直接就可以查找出來:

 Nuget命令行:

Install-Package Autofac -Version 4.8.1

 創建一個依賴關係類:

首先我們定義一個服務介面=>IService

    /// <summary>
    /// 服務介面
    /// 描述:為了方法的繼承和擴展更好的演示下麵的例子
    /// </summary>

    public interface IService
    {
        //定義一個輸出方法
        void PrintWord();
    }

然後我們在創建一個服務類去實現介面(IService)=>Service

/// <summary>
    /// 服務類具體實現
    /// </summary>
    public class Service : IService
    {
        //輸出方法的實現
        public void PrintWord()
        {
            Console.WriteLine("我是service列印的Hello word");
        }
    }

好了現在我們有了一個服務介面和一個服務類 ,並且類下麵實現了輸出會列印:我是service列印的Hello word。常規我們想調用這個方法我們都是在mian函數中示例化該類進行調用,類似於這樣

            IService service = new Service();
            service.PrintWord();
            //或者
            Service service2 = new Service();
            service2.PrintWord();

但是今天我們說的不是這些我們說的另外的方式。那我們看看 autofac是怎麼調用的。

註冊容器

其實萬變不離其宗,不管是autofac,unity,spring.net等,其實都是這麼一個套路就是先註冊容器然後才能從容器取出,其實這個也非常好理解容器本身是沒有東西的,你想用東西就要提前放進去,只有容器有了你請求才會給你。不同的插件只不過是各自的封裝方法或者形式存在著差異。autofac的註冊方式:

           // 創建容器
            var builder = new ContainerBuilder();
            //註冊對象
            builder.RegisterType<Service>().As<IService>();
            Container = builder.Build();

這個時候我們就相當於把service類放入了容器,這樣在後面你才可以取出來使用。

使用容器

這裡我寫了兩個使用的方法根據不同情況使用把:

            //使用方法一
            using (var ioc = Container.BeginLifetimeScope())
            {
                var service = ioc.Resolve<IService>();
                service.PrintWord();
            }

            //使用方法二
            //var service = Container.Resolve<IService>();
            //service.PrintWord();

運行

我們可以任意註釋一個方法來檢測一下結果:

這樣我們就完成了autofac的簡單運用。

AutoFac新手村

通過上面的例子我們已經知道autofac的基本運用。基本運用還不行我們還要知道一些知識。

多構造函數

第一種:就是單純的有多個構造

如果我們同一個類存在多個構造函數會給我們一個什麼結果哪這個在有時候是非常重要的。

所以我們修改我們的service類:

 /// <summary>
    /// 服務類具體實現
    /// </summary>
    public class Service : IService
    {
        //預設構造
        public Service() {
            Console.WriteLine("我是service的預設構造");
        }
        //一個參數的構造
        public Service(int a)
        {
            Console.WriteLine("我是service的一個參數構造");
        }
        //兩個參數的構造
        public Service(int a,int b)
        {
            Console.WriteLine("我是service的兩個參數構造");
        }
        //輸出方法的實現
        public void PrintWord()
        {
            Console.WriteLine("我是service列印的Hello word");
        }
    }

其他都不變運行代碼:

這裡就是執行了預設構造,所有在一個類有多個構造情況下預設的形式是返回給我們預設構造函數的類實例。

第二種:多構造參數類型並且參數類型也註冊容器

這個什麼意思哪就是說有兩個類,其中一個類的構造函數參數是另一個類。並且參數類型也進行註冊容器

我們增加一個ServiceTwo類:

 public class ServiceTwo :IService
    {
        //輸出方法的實現
        public void PrintWord()
        {
            Console.WriteLine("我是serviceTwo列印的Hello word");
        }
    }

修改service類中的一個參數構造為:

        //一個參數的構造
        public Service(ServiceTwo two)
        {
            Console.WriteLine("我是service的一個參數構造");
        }

main函數增加註冊:

            //註冊對象
            builder.RegisterType<Service>().As<IService>();
            builder.RegisterType<ServiceTwo>();
            Container = builder.Build();

然後運行:

這裡就和上面的結果不一樣了,所有在使用時需要註意,autofac官方解釋為:當使用基於反射的組件時, Autofac 自動為你的類從容器中尋找匹配擁有最多參數的構造方法。

說白了就是如果使用註冊類並且註冊類多構造函數,並且其構造參數為其他註冊類時候,查找的構造函數包含註冊類最多的構造函數返回。

 指定構造函數

由容器掌握我們的構造函數總是不好的,所有我們要自己指定想創建誰創建誰=>UsingConstructor(參數類型)可以多個

在這裡需要註意我們既然指定了構造函數就要為構造函數傳參不然會抱錯,參數可以是註冊時候傳也可以解析時候傳,我寫了一個解析時候傳的:

            // 創建容器
            var builder = new ContainerBuilder();
            //註冊對象
            builder.RegisterType<Service>().As<IService>().UsingConstructor(typeof(int), typeof(int));
           // builder.RegisterType<ServiceTwo>();
            Container = builder.Build();

            //使用方法一
            using (var ioc= Container.BeginLifetimeScope())
            {
                var service = ioc.Resolve<IService>(new NamedParameter("a", 1), new NamedParameter("b", 1));
                service.PrintWord();
            }

運行結果:

 類的覆蓋

如果我兩個類或者多個類同時實現一個介面並且註冊的時候都與介面做了關聯。

那麼會存在覆蓋現象。

下麵我們把main函數改造讓serviceTwo也註冊與IService關聯

            // 創建容器
            var builder = new ContainerBuilder();
            //註冊對象
            builder.RegisterType<Service>().As<IService>();
            builder.RegisterType<ServiceTwo>().As<IService>();
            Container = builder.Build();

            //使用方法一
            using (var ioc = Container.BeginLifetimeScope())
            {
                var service = ioc.Resolve<IService>();
                service.PrintWord();
            }

運行結果:

這個時候我們得到的是serviceTwo類的示例。如果改變Service和ServiceTwo的位置就會返回service實例。

當然我沒也可以阻止這個行為使用PreserveExistingDefaults()方法:

            //註冊對象
            builder.RegisterType<Service>().As<IService>();
            builder.RegisterType<ServiceTwo>().As<IService>().PreserveExistingDefaults();

再次運行就不會覆蓋:

 屬性註入

WithProperty:綁定一個屬性和他的值

我們給ServiceTwo類添加name屬性並擴展一個列印方法:

 public string name { get; set; }

        public void PrintName()
        {
            Console.WriteLine($"name屬性:{name}");
        }

然後main函數改為

            builder.RegisterType<Service>().As<IService>();
            builder.RegisterType<ServiceTwo>().WithProperty("name", "張三");
            Container = builder.Build();

            //使用方法一
            using (var ioc = Container.BeginLifetimeScope())
            {
                var service = ioc.Resolve<ServiceTwo>();
                service.PrintName();
            }

運行結果:

方法註入

OnActivating:方法註入

我們在ServiceTwo類添加設置名稱方法

  public void setName()
        {
            name = "李四";
        }

然後main函數改為:

builder.RegisterType<ServiceTwo>().OnActivating(e=> {
                e.Instance.setName();
            });

運行結果:

 

AutoFac集成-MVC

首先創建mvc項目就不過多解釋了。

引用dll:

這裡需要引用兩個dll文件: Autofac.Mvc5和 Autofac。註意這裡我的是mvc5所以我安裝的Autofac.Mvc5 這個要根據mvc版本做對應不然會報錯。

 

 

通過nuget安裝就可以了。

相關類

還是我們的Service類和IService類來做示例演示:

    /// <summary>
    /// 服務介面
    /// 描述:為了方法的繼承和擴展更好的演示下麵的例子
    /// </summary>

    public interface IService
    {
        //定義一個輸出方法
        void PrintWord();
    }

    /// <summary>
    /// 服務類具體實現
    /// </summary>
    public class Service : IService
    {
        //預設構造
        public Service()
        {
            Console.WriteLine("我是service的預設構造");
        }
        //輸出方法的實現
        public void PrintWord()
        {
            System.Diagnostics.Debug.WriteLine("調起了service中的方法");
        }
    }

配置文件

配置Global文件,來註入控制器。下麵我只做構造函數註入和屬性註入

protected void Application_Start()
        {

            var builder = new ContainerBuilder();

            // 通過程式集註冊所有控制器和屬性註入
            //builder.RegisterControllers(typeof(MvcApplication).Assembly);
            builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();



            builder.RegisterType<Service>().As<IService>();
            // 將依賴性分解器設置為AutoFac。
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

控制器如何使用:

打開home控制器:

  public class HomeController : Controller
    {

        /// <summary>
        /// 構造函數註入
        /// </summary>
        /// <param name="serviceClient"></param>
        public HomeController(IService serviceClient)
        {
            this.Service = serviceClient;
        }
        public IService Service;

        /// <summary>
        /// 屬性註入
        /// </summary>
        /// <returns></returns>
       // public IService Service2 { get;  set; }
        public ActionResult Index()
        {
            //使用方法一
            Service.PrintWord();
            //Service2.PrintWord();

            return View();
        }

    }

運行看效果:

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • dfs
    sdfsf ...
  • 前言 這篇文章是WPF框架系列的最後一篇,在這裡我想闡述一下我對框架設計的理解。 我對框架設計的理解是這樣的: 框架設計不應該局限於任何一種設計模式,我們在設計框架時,應該將設計模式揉碎,再重組;這樣設計出來的框架才具有一戰之力。 框架設計應該根據項目團隊成員水平量身定製。 我上一篇文章《我們都知道 ...
  • Console.WriteLine("100-1000的水仙花數有"); for (int i = 100; i < 1000; i++) { int a = i / 100 % 10;//百位 int b = i / 10 % 10;//十位 int c = i % 10;//個位 if (a * ...
  • VC2010和VC2017的標準庫中,string(或wstring)的數據結構和操作有所不同,所以在將這兩種數據作為參數在兩個系統產生的函數中傳遞時會出現亂碼(string和wstring在2017下必須是引用傳遞) ...
  • 作者:依樂祝 原文地址:https://www.cnblogs.com/yilezhu/p/9866068.html 在本文中,我將解釋命令模式,以及如何利用基於命令模式的第三方庫來實現它們,以及如何在ASP.NET Core中使用它來解決我們的問題並使代碼簡潔。因此,我們將通過下麵的主題來進行相關 ...
  • 基礎環境配置 功能變數名稱和伺服器請先自行購買 基於 雲伺服器ECS 創建一個應用實例,選擇系統鏡像為 Ubuntu 16.04 ,在本機通過 SSH 進行遠程連接,併進行相關配置 安裝並配置 Nginx 配置 default 文件,在文件末尾配置如下節點信息 檢測配置並更新 安裝 DotNetCore 請 ...
  • 這篇我們學習水晶報表,報表呈現的數據源是IEnumerable<T>。比如下麵的數據: using System; using System.Collections.Generic; using System.Linq; using System.Web; using Insus.NET.Model ...
  • 在ASP.NET MVC項目開發,還是需要創建一些Web Page來實現一些功能,如呈現報表等... 但是一旦項目的.ASPX網頁太多了,其中的程式代碼也會有代碼冗餘,出現這些情況,我們得需要對這些代碼進行重構。 比如,項目中需要呈現很多報表,就會創建許多.aspx網頁: 所有呈現報表的.aspx. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...