.NET Core 依賴注入 Microsoft.Extensions.DependencyInjection

文章目錄

  • 前言
  • 什么是依賴注入
  • C# 使用依賴注入
    • 框架介紹
  • Microsoft.Extensions.DependencyInjection
    • Nuget安裝
    • 簡單單例使用
      • 打印結果
    • 自動裝配
      • 舉例
      • 自動裝配測試用例
      • 打印結果
      • 自動裝配執行順序
        • 測試用例
        • 有歧義構造函數
        • 漸進式構造函數
        • 循環依賴
      • 自動裝配結論
    • 手動裝配
      • 手動注入
      • 別名注入
    • 依賴注入的構造順序
  • 結尾

前言

依賴注入是一個非常重要的編程思想,就和面向過程和面向對象一樣,IOC和控制反轉是一種解耦的編程思想。

什么是依賴注入

[C#]理解和入門依賴注入

為什么要用IOC:inversion of controll反轉控制(把創建對象的權利交給框架)

C# 使用依賴注入

框架介紹

目前.NET 有兩個最優的依賴注入框架

  • Microsoft.Extensions.DependencyInjection:微軟官方依賴注入框架,聽說在.net core 8.0得到了最強的性能提升
  • Autofac:聽說也是最強的依賴注入框架,性能強,開銷低,功能完善。

Dependency injection in ASP.NET Core

Autofac 官網

深入淺出依賴注入容器——Autofac

Microsoft.Extensions.DependencyInjection

目前打算用微軟的IOC,畢竟是官方背書,性能有保證。

C# 依賴注入IServiceCollection的AddSingleton方法使用

Nuget安裝

在這里插入圖片描述

簡單單例使用

聲明個測試類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace NETCore8.Models
{public class Person{public int Id { get; set; }public string ?Name { get; set; }public int Age { get; set; }}
}

主函數代碼

using Microsoft.Extensions.DependencyInjection;
using NETCore8.Models;
using Newtonsoft.Json;
using System.ComponentModel.Design;namespace NETCore8
{internal class Program{static void Main(string[] args){//構造依賴注入容器IServiceCollection services = new ServiceCollection();//注入Person單例,生命周期暫時不展開services.AddSingleton<Person>();var builder = services.BuildServiceProvider();//初始化單例var res = builder.GetService<Person>();res.Name = "小劉";res.Age = 15;Console.WriteLine(JsonConvert.SerializeObject(res));//從容器中拿到Person單例,確認是否已被賦值為小劉var res2 = builder.GetService<Person>();Console.WriteLine(JsonConvert.SerializeObject(res2));//修改單例,查看容器中的單例是否被修改res2.Name = "小紅";res2.Age = 23;//再從容器中拿出單例var res3 = builder.GetService<Person>();Console.WriteLine(JsonConvert.SerializeObject(res3));Console.WriteLine("Hello, World!");Console.ReadKey();}}
}

打印結果

在這里插入圖片描述
這個說明這個單例一旦被修改了,容器中的數據就會被修改。但是這樣僅僅是和全局靜態的效果一樣。依賴注入沒有這么簡單

自動裝配

自動裝配的意思就是自動依賴注入。就是你不需要主動去聲明構造函數,IOC容器會自動幫你去使用構造函數。

舉例

這里為了簡單說明,這里只使用單例自動裝配舉例。

namespace IOC_Test.Models
{public class Person{public int Id { get; set; }public string Name { get; set; }public int Age {  get; set; }   }
}
namespace IOC_Test.Services
{public class PersonService{public Person Person { get; set; }/// <summary>/// 無參構造函數/// </summary>public PersonService() {Person = new Person();}/// <summary>/// 有參構造函數,IOC是選擇盡可能多的參數構造/// </summary>/// <param name="person"></param>public PersonService(Person person){this.Person = person;}}
}

自動裝配測試用例

using IOC_Test.Models;
using IOC_Test.Services;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;namespace IOC_Test
{internal class Program{static void Main(string[] args){IServiceCollection services = new ServiceCollection();//注入依賴services.AddSingleton<Person>();services.AddSingleton<PersonService>();//生成IOC容器var builder = services.BuildServiceProvider();//兩次打印,第一次打印PersonService的Person{var res = builder.GetService<PersonService>();Console.WriteLine(JsonConvert.SerializeObject(res?.Person));}//修改Person,看看PersonService里面是不是會受影響{var res = builder.GetService<Person>();res.Name = "小王";res.Age = 10;}//再次打印,如果被修改,那么就說明是自動裝配。如果沒被修改,就說明沒有將Person自動注入到PersonService{var res = builder.GetService<PersonService>();Console.WriteLine(JsonConvert.SerializeObject(res?.Person));}Console.WriteLine("Hello, World!");Console.ReadLine();}}
}

打印結果

在這里插入圖片描述

自動裝配執行順序

測試用例

這里我們新建一個Dog

namespace IOC_Test.Models
{public class Dog{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }}
}

Person

namespace IOC_Test.Models
{public class Person{public int Id { get; set; }public string Name { get; set; }public int Age {  get; set; }   }
}

PersonService

namespace IOC_Test.Services
{public class PersonService{public Person Person { get; set; }public Dog Dog { get; set; }/// <summary>/// 無參構造函數/// </summary>public PersonService() {Person = new Person();}}
}

主函數

namespace IOC_Test
{internal class Program{static void Main(string[] args){IServiceCollection services = new ServiceCollection();//注入依賴services.AddSingleton<Person>();services.AddSingleton<PersonService>();services.AddSingleton<Dog>();//生成IOC容器var builder = services.BuildServiceProvider();//兩次打印,第一次打印PersonService{var res = builder.GetService<PersonService>();Console.WriteLine(JsonConvert.SerializeObject(res));}//修改Person和Dog,看看PersonService里面是不是會受影響{var person = builder.GetService<Person>();person.Name = "小王";person.Age = 10;var dog = builder.GetService<Dog>();dog.Name = "旺財";dog.Age = 2;}//再次打印,查看自動裝配如何執行{var res = builder.GetService<PersonService>();Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine("Hello, World!");Console.ReadLine();}}
}
有歧義構造函數
namespace IOC_Test.Services
{public class PersonService{public Person Person { get; set; }public Dog Dog { get; set; }/// <summary>/// 無參構造函數/// </summary>public PersonService() {Person = new Person();}public PersonService(Person person){this.Person = person;}public PersonService(Dog dog) {this.Dog = dog;}}
}

如果構造函數出現歧義,比如這里既可以選擇Person構造,又可以選擇Dog構造,會報錯
在這里插入圖片描述

漸進式構造函數
namespace IOC_Test.Services
{public class PersonService{public Person Person { get; set; }public Dog Dog { get; set; }/// <summary>/// 無參構造函數/// </summary>public PersonService() {Person = new Person();}public PersonService(Person person){this.Person = person;}public PersonService(Person person,Dog dog) {this.Person= person;this.Dog = dog;}}
}

運行成功
在這里插入圖片描述

循環依賴

Person注入Dog,Dog注入Person,看看效果如何

namespace IOC_Test.Models
{public class Person{public Dog Dog { get; set; }public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public Person(Dog dog){Dog = dog;}}
}
namespace IOC_Test.Models
{public class Dog{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public Person Person { get; set; }public Dog(Person person){Person = person;}}
}

在這里插入圖片描述

自動裝配結論

自動裝配是盡可能主動去裝配服務,如果出現裝配歧義,循環依賴,那么就會主動拋出異常。自動裝配可以極大的減少對構造函數維護,我們不需要知道服務是怎么聲明的,IOC容器會幫助我們自動聲明相互之間的依賴。這張圖就能很好的解釋自動裝配的效果

在這里插入圖片描述

手動裝配

自動裝配是由IOC容器自動裝配的類。如果需要裝配多個同類的服務,那就要手動進行區別了。

手動注入

internal class Program
{static void Main(string[] args){IServiceCollection services = new ServiceCollection();services.AddSingleton<Person>(sp =>{var res = new Person() {Name = "小紅",Age = 19};return res;});//生成容器var builder = services.BuildServiceProvider();{var res = builder.GetService<Person>();Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine("Hello, World!");Console.ReadLine();}
}

在這里插入圖片描述

別名注入

namespace IOC_Test
{internal class Program{static void Main(string[] args){IServiceCollection services = new ServiceCollection();services.AddKeyedSingleton<Person>("A",(sp,key) =>{var res = new Person() {Name = "小紅",Age = 19};return res;});services.AddKeyedSingleton<Person>("B", (sp, key) =>{var res = new Person(){Name = "小藍",Age = 23};return res;});//生成容器var builder = services.BuildServiceProvider();//獲取服務,當Key找不到時自動返回Null{var res = builder.GetService<Person>();Console.WriteLine("獲取默認服務");Console.WriteLine(JsonConvert.SerializeObject(res));}{var res = builder.GetKeyedService<Person>("A");Console.WriteLine("獲取A,Person");Console.WriteLine(JsonConvert.SerializeObject(res));}{var res = builder.GetKeyedService<Person>("B");Console.WriteLine("獲取B,Person");Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine("Hello, World!");Console.ReadLine();}}
}

在這里插入圖片描述

聲明別名的服務將不會自動裝配,即使聲明的別名相同。建議使用多個不同名的服務來自動裝配。手動聲明別名需要手動裝配對應關系

也可以在輸入的時候主動拿到按照Key去尋找服務。

internal class Program
{static void Main(string[] args){IServiceCollection services = new ServiceCollection();//依賴注入是使用的時候去構造,所以聲明順序不影響實際運行順序,有點類似于回調函數services.AddKeyedSingleton<Person>("A",(sp,key) =>{//Console.WriteLine(key);var res = new Person() {Name = "小紅",Age = 19};return res;});services.AddKeyedSingleton<PersonService>("A", (sp, key) =>{return new PersonService(sp.GetKeyedService<Person>(key));});//生成容器var builder = services.BuildServiceProvider();//獲取服務{var res = builder.GetKeyedService<Person>("A");Console.WriteLine("獲取默認服務");Console.WriteLine(JsonConvert.SerializeObject(res));}//獲取服務{var res = builder.GetKeyedService<PersonService>("A");Console.WriteLine("獲取默認服務");Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine("Hello, World!");Console.ReadLine();}
}

依賴注入的構造順序

依賴注入是使用的時候去生成,而不是注入的時候生成

namespace IOC_Test
{internal class Program{static void Main(string[] args){IServiceCollection services = new ServiceCollection();services.AddKeyedSingleton<Person>("A",(sp,key) =>{Console.WriteLine($"構造函數執行,key[{key}]");var res = new Person() {Name = "小紅",Age = 19};return res;});//生成容器var builder = services.BuildServiceProvider();//獲取服務{Console.WriteLine("獲取Key[A]服務");var res = builder.GetKeyedService<Person>("A");Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine("Hello, World!");Console.ReadLine();}}
}

在這里插入圖片描述

結尾

IOC容器還有許多別的功能,比如別名,接口注入,注解注入,聲明周期等。這個我還不太了解。現在的單例自動裝配已經基本滿足了我的功能,我以后有時間會去深入了解。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/210789.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/210789.shtml
英文地址,請注明出處:http://en.pswp.cn/news/210789.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Git:版本控制的藝術與實踐

引言&#xff1a; 在軟件開發領域&#xff0c;版本控制是至關重要的一環。它幫助我們跟蹤代碼的變化、管理團隊協作、回溯歷史記錄以及解決沖突等。而Git作為目前最流行的分布式版本控制系統&#xff0c;已經成為了開發者們的必備工具。本文將深入探討Git的核心概念、常用命令以…

使用Docker安裝Superset并設置Oracle訪問和使用PG作Meta數據庫

一、安裝 Docker 安裝一個linux&#xff0c;可以是Centos或Ubuntu&#xff0c;如果是Centos 7.X&#xff0c;那么要注意先將系統自帶的docker先刪除。下文以Centos7.9為例 #刪除自帶的不完整版本 yum remove docker docker-client docker-client-latest \docker-common docker-…

調用win32 api獲取電腦名字和系統目錄

學習一下幾個函數的功能&#xff0c;和調用方式&#xff1b; void CBasenameView::OnDraw(CDC* pDC) {CBasenameDoc* pDoc GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereCString str1;TCHAR myname1[50], myname2[50], mydirname1[50], myd…

常見的Linux系統版本

在介紹常見的Linux系統版本之前&#xff0c;首先需要區分Linux系統內核與Linux發行套件系統的不同。Linux系統內核指的是一個由Linus Torvalds負責維護&#xff0c;提供硬件抽象層、硬盤及文件系統控制及多任務功能的系統核心程序。而Linux發行套件系統是我們常說的Linux操作系…

【Vue+Python】—— 基于Vue與Python的圖書管理系統

文章目錄 &#x1f356; 前言&#x1f3b6;一、項目描述?二、項目展示&#x1f3c6;三、撒花 &#x1f356; 前言 【VuePython】—— 基于Vue與Python的圖書管理系統 &#x1f3b6;一、項目描述 描述&#xff1a; 本項目為《基于Vue與Python的圖書管理系統》&#xff0c;項目…

Minio保姆級教程

轉載自&#xff1a;www.javaman.cn Minio服務器搭建和整合 1、centos安裝minio 1.1、創建安裝目錄 mkdir -p /home/minio1.2、在線下載minio #進入目錄 cd /home/minio #下載 wget https://dl.minio.io/server/minio/release/linux-amd64/minio1.3、minio配置 1.3.1、添加…

Flutter筆記:滑塊及其實現分析1

Flutter筆記 滑塊分析1 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 郵箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/134900784 本文從設計角度&#…

SQL命令---刪除字段

介紹 使用sql語句刪除表字段。 命令 alter table 表名 drop 字段名;例子 刪除a表中的name字段。 alter table a drop name;下面是執行刪除后的表結構&#xff1a;

微服務實戰系列之通信

前言 掰個指頭數一數&#xff0c;博主的“微服務實戰系列”從無到有&#xff0c;從零走到了十五。如果比作時鐘&#xff0c;剛好走過了一刻度。 當初為什么要做這個系列&#xff0c;博主想了又想&#xff0c;私以為作為當下軟件領域的幾個“hot spot”之一&#xff0c;又乘著…

探秘機器學習核心邏輯:梯度下降的迭代過程 (圖文詳解)

一 需求解函數 f() 和 g()函數分別為求y值和求導數的函數。 目的&#xff1a;求該函數的最小值&#xff1a; 代碼&#xff1a; import numpy as np import matplotlib.pyplot as plt f lambda x : (x - 3.5) ** 2 - 4.5 * x 10 g lambda x : 2 * (x - 3.5) - 4.5x np.l…

架構LAMP

目錄 1.什么是LAMP 2.LAMP組成及作用 3.搭建Apache httpd服務 4.編譯安裝mysqld 服務 5.編譯安裝PHP 解析環境 6.安裝論壇 1.什么是LAMP LAMP架構是目前成熟的企業網站應用模式之一&#xff0c;指的是協同工作的一整套系統和相關軟件&#xff0c;能夠提供動態Web站點服務…

MATLAB算法實戰應用案例精講-【人工智能】漫談自動駕駛

目錄 常用數據集 一、自動駕駛領域數據集 1. KITTI數據集 2.CityScapes數據集 3.BDD100K數據集

go與ioc

在Go開發服務端程序時&#xff0c;使用IoC&#xff08;Inversion of Control&#xff09;機制并不像在Java等語言中那樣普遍。Go語言的設計哲學傾向于簡潔和直接&#xff0c;更注重代碼的可讀性和可維護性。 在Go中&#xff0c;通常會使用依賴注入&#xff08;Dependency Inje…

【Python】視頻剪輯小程序

近期遇到一些錄制的視頻需要剪輯。 手機上剪輯操作很耗時&#xff0c;有幾個G的視頻&#xff0c;花了一天的空余時間去剪輯。電腦上也有格式工廠&#xff0c;有很方便。 可是學了Pthon&#xff0c;又無意中了解到了moviepy這個庫&#xff0c;于是自己寫了個簡單的視頻剪輯程序。…

Windows安裝kafka

壓縮包下載地址&#xff1a;https://www.apache.org/dyn/closer.cgi?path/kafka/3.6.1/kafka_2.13-3.6.1.tgz 啟動kafka步驟 zookeeper-server-start.bat rem 閉命令提示符窗口的命令回顯&#xff0c;這樣在運行腳本時不會顯示腳本的具體命令內容 echo offrem 命令行啟動未…

Proteus仿真--8×8LED點陣屏仿電梯數字滾動顯示

本文介紹基于88LED點陣屏仿電梯數字滾動顯示設計&#xff08;完整仿真源文件及代碼見文末鏈接&#xff09; 仿真圖如下 其中K1-K5的5個按鍵分別代表不同樓層&#xff0c;摁下按鍵后在8X8LED上便會顯示到對應樓層的跳變信息&#xff0c;模擬電梯的運作 仿真運行視頻 Proteus仿…

nodejs多線程,fork和Worker

一、前言 javascript是單線程執行的&#xff0c;如果想要多線程執行&#xff0c;那么相當于再運行一個node,其實不該理解成多線程&#xff0c;更像是多進程。 二、Worker(‘worker_threads’模塊) worker有點類似exec&#xff0c;直接再cmd執行node命令&#xff0c;不同的是兩…

《安富萊嵌入式周報》第328期:自主微型機器人,火星探測器發射前失誤故障分析,微軟推出12周24期免費AI課程,炫酷3D LED點陣設計,MDK5.39發布

周報匯總地址&#xff1a;嵌入式周報 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬漢嵌入式論壇 - Powered by Discuz! 更新一期視頻教程&#xff1a; 【實戰技能】 單步運行源碼分析&#xff0c;一期視頻整明白FreeRTOS內核源碼框架和運行…

【STM32】TIM定時器基本定時功能

第一部分&#xff1a;定時器基本定時的功能&#xff1b; 第二部分&#xff1a;定時器的輸出比較功能&#xff1b; 第三部分&#xff1a;定時器輸入捕獲的功能&#xff1b; 第四部分&#xff1a;定時器的編碼接口。 1 TIM簡介 TIM&#xff08;Timer&#xff09;定時器&#…

在OpenCV基于深度學習的超分辨率模型實踐

1. 引言 OpenCV是一個開源的計算機視覺庫&#xff0c;擁有大量優秀的算法。基于最新的合并&#xff0c;OpenCV包含一個易于使用的接口&#xff0c;主要用于實現基于深度學習方法的超分辨率&#xff08;SR&#xff09;。該接口包含預先訓練的模型&#xff0c;這些模型可以非常容…