【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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...