Microsoft.Extensions 简介
Microsoft.Extensions 简介
一、Microsoft.Extensions 简介
.NET Extensions 是一套官方的、开源的、跨平台的 API 集合,提供了一些常用的编程模式和实用工具,例如依赖项注入、日志记录、缓存、Host以及配置等等。该项目的大多数 API 都被用在 .NET 平台的各个应用框架上,如 http://ASP.NET Core,Xamarin 等等。虽然 http://ASP.NET 使用了很多这些 API 但 http://ASP.NET 并没有与它们紧密耦合。你也可以在控制台应用程序、WinForm以及WPF应用程序上使用它们。总结一句就是:它是官方造的“轮子”
**
NET API browser 中的 .NET Platform Extensions
.NET Platform Extensions 包括下面所列的包,由于 .NET 5 正在整合各个代码仓库,所以 .NET Extension 中的部分代码仓库已经分别以迁移到了 dotnet/runtime 和 dotnet/aspnetcore 这两个仓库中。## 移动到 dotnet/runtime 的包:## **Caching**Microsoft.Extensions.Caching.Abstractions
Microsoft.Extensions.Caching.Memory## ConfigurationMicrosoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Abstractions
Microsoft.Extensions.Configuration.Binder
Microsoft.Extensions.Configuration.CommandLine
Microsoft.Extensions.Configuration.EnvironmentVariables
Microsoft.Extensions.Configuration.FileExtensions
Microsoft.Extensions.Configuration.Ini
Microsoft.Extensions.Configuration.Json
Microsoft.Extensions.Configuration.UserSecrets
Microsoft.Extensions.Configuration.Xml## Dependency InjectionMicrosoft.Extensions.DependencyInjection
Microsoft.Extensions.DependencyInjection.Abstractions## File ProvidersMicrosoft.Extensions.FileProviders.Abstractions
Microsoft.Extensions.FileProviders.Composite
Microsoft.Extensions.FileProviders.Physical
File System Globbing
Microsoft.Extensions.FileSystemGlobbing## HostingMicrosoft.Extensions.Hosting
Microsoft.Extensions.Hosting.Abstractions
Http Client Factory
Microsoft.Extensions.Http## LoggingMicrosoft.Extensions.Logging
Microsoft.Extensions.Logging.Abstractions
Microsoft.Extensions.Logging.Configuration
Microsoft.Extensions.Logging.Console
Microsoft.Extensions.Logging.Debug
Microsoft.Extensions.Logging.EventLog
Microsoft.Extensions.Logging.EventSource
Microsoft.Extensions.Logging.Testing
Microsoft.Extensions.Logging.TraceSource## OptionsMicrosoft.Extensions.Options
Microsoft.Extensions.Options.ConfigurationExtensions
Microsoft.Extensions.Options.DataAnnotations## PrimitivesMicrosoft.Extensions.Primitives## 移动到 dotnet/aspnetcore 的包:## ConfigurationMicrosoft.Extensions.Configuration.KeyPerFile## File ProvidersMicrosoft.Extensions.FileProviders.Embedded
Microsoft.Extensions.FileProviders.Embedded.Manifest.Task## Health ChecksMicrosoft.Extensions.Diagnostics.HealthChecks
Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions## JS InteropMicrosoft.JSInterop
Mono.WebAssembly.Interop## LocalizationMicrosoft.Extensions.Localization
Microsoft.Extensions.Localization.Abstractions## LoggingMicrosoft.Extensions.Logging.AzureAppServices## Object PoolMicrosoft.Extensions.ObjectPool
Web Encoders
Microsoft.Extensions.WebEncoders## 目前仍在 dotnet/extensions 的包:## CachingMicrosoft.Extensions.Caching.SqlServer
Microsoft.Extensions.Caching.StackExchangeRedis## ConfigurationMicrosoft.Extensions.Configuration.NewtonsoftJson## HostingMicrosoft.Extensions.Hosting.Systemd
Microsoft.Extensions.Hosting.WindowsServices## Http Client FactoryMicrosoft.Extensions.Http.Polly## LoggingMicrosoft.Extensions.Logging.Analyzers (has not been released to NuGet.org as of writing)
Microsoft.Extensions.DependencyInjection.Specification.Tests
二、什么是依赖注入?
**
依赖注入,字面理解就是将依赖注入到你的代码中,那么为什么需要将依赖注入到你的代码中呢?以及怎么注入到你的代码?下面我们来一步一步来了解整个过程。
1)首先,通常情况下当我们要使用另外一个类型时我们会使用下面的代码来生成一个该类型的实例。
var a = new ClassA();
a.MehtodA();
此时相当于我们的代码依赖了ClassA,一旦 ClassA 发生了改变我们的代码也就需要发生相应的改变,这不符合松耦合的设计原则,那么我们应该怎么做呢?
2)为了让我们的代码不直接依赖于 ClassA 我们来定义一个接口 InterfaceA,
interface InterfaceA
{void MethodA();
}
并让== ClassA 实现该接口==,那么我们就可以这样写我们的代码了,
InterfaceA a = new ClassA();
a.MethodA();
此时我们的代码本质上是对 InterfaceA 的依赖,并不关心 InterfaceA 的具体实现。不过目前好像没什么鸟用,因为我们的代码中仍然需要显式实例化 ClassA,这时候我们就希望能有一个神奇的工具能给我们一个 InterfaceA 的实例了。
3)现在 IoC 容器就闪亮登场了(IoC, Inversion of Control / 控制反转),它可以使用多种方式给我们的代码中注入我所需要的 InterfaceA 实例,下面的代码就是利用构造函数注入依赖。
public class MyCode
{private InterfaceA _ia;public MyCode(InterfaceA ia){_ia = ia;}public void MyMethod(){_ia.MethodA();}
}
这样在我们的代码里就看不到 ClassA 了,我们的代码也就脱离了对 ClassA的依赖,实现了松耦合,也践行了部分面向对象的设计原则,如依赖倒置(DIP)原则。
下面我们使用 Microsoft.Extensions 中的 DependencyInjection 容器(在下文中我们简称为DI容器)来实现上面示例的完整代码。
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;namespace DemoCode
{class Program{static void Main(string[] args){//初始化容器IServiceCollection ioc = new ServiceCollection();//这里的是添加服务到容器中//Transient指的是服务实例的生命周期,即每次请求服务的时候都会创建一个新的实例ioc.TryAddTransient<MyCode>();ioc.TryAddTransient<InterfaceA, ClassA>();//创建serviceProvider对象来获取服务的实例var serviceProvider = ioc.BuildServiceProvider();var myCodeinstance = serviceProvider.GetService<MyCode>();//调用我们定义的方法myCodeinstance .Run();}}//public class MyCode{private InterfaceA _ia;public MyCode(InterfaceA ia){_ia = ia;}public void Run(){_ia.MethodA();}}//定义服务的接口public interface InterfaceA{void MethodA();}//服务的具体实现public class ClassA : InterfaceA{public void MethodA(){Console.WriteLine("MethodA 被调用");}}
}
依赖注入以及控制反转都属于设计模式(Design Pattern),并且通常情况下,要实现控制反转就需要基于依赖注入。它们都是为了遵从面向对象语言的设计原则 S.O.L.I.D 而产生的。
S: Single responsibility / 单一职责
O: Open closed / 开闭原则(对扩展开放,对修改关闭)
L: Liskov substitution / 里氏替换
I: Interface segregation / 接口分离
D: Dependency inversion / 依赖倒置
关于S.O.L.I.D 的更多内容可以查看下面这篇文章,
S.O.L.I.D: The First 5 Principles of Object Oriented Designscotch.io

三、DI容器的使用方法
1、引用
Microsoft.Extensions.DependencyInjection.Abstractions
Microsoft.Extensions.DependencyInjection
这两个包含了容器的抽象以及容器的具体实现,其中Microsoft.Extensions.DependencyInjection.Abstractions 为抽象,Microsoft.Extensions.DependencyInjection 则为具体实现。
当你要在自己的程序中使用时,使用nuget包管理工具安装 Microsoft.Extensions.DependencyInjection 包即可。
2、主要类型
1、引用类型
使用 DI 容器需要熟悉下面的接口与类型,Microsoft.Extensions.DependencyInjection.IServiceCollection,该接口包含了一系列 Add 扩展方法来添加你的服务,该接口的默认实现为 Microsoft.Extensions.DependencyInjection.ServiceCollection 类。
容器接口叫做 IServiceCollection 是因为 “微软”将容器中的类型视为我们程序所需的服务,有了这个前提将它命名为 “ServiceCollection”也就非常合理了。
System.IServiceProvider,使用 IServiceCollection 的扩展方法 BuildServiceProvider() 可以得到一个默认的 ServiceProvider 对象来让我们获取服务实例,ServiceProvider 实现了IServiceProvider 接口,该接口包含了一个 GetService() 方法来获取服务。IServiceProvider 接口的默认实现为 Microsoft.Extensions.DependencyInjection.ServiceProvider 类。
2、IServiceCollection,添加服务与生命周期
IServiceCollection 接口包含一系列的扩张方法让我们方便的添加服务,常用的包括下面三个方法,
- AddTransient,添加生命周期为Transient(短暂)的服务,这样的服务在每次被请求是都会创建一个新的实例。
- AddSingleton
,添加生命周期为Singleton(单例)的服务,这样的服务只有在首次请求是创建一个新的实例,之后都会使用这个实例。 - AddScoped,添加生命周期为Scoped(域内)的服务,这样的服务在一个自定义的“作用域”范围内是单例的。例如,在
http://ASP.NET Core 中 Scoped 服务在每一次请求中都是一个实例。 除此之外你也可以使用 Add 方法,并使用
ServiceLifetime 在参数中指定生命周期。
除了上面这三个常用方法之外,还有 TryAddTransient、TryAddSingleton、TryAddScoped 这三个用于添加服务的方法,与之前所提三个方法的区别在于带 Try 的这三个方法在添加服务时会检查服务是否已存在,若已经存在则不再添加。
3、IServiceProvider,获取服务与注入依赖
你可以使用 IServiceCollection 的 BuildServiceProvider() 方法来获取 IServiceProvider 对象,使用 GetServices 方法便可以获取你添加到容器中的服务,对于 Transient 和 Singleton 的服务使用这个方法便可以实现其对应的生命周期逻辑。
Scoped的情况相对有点复杂,如果你直接使用 IServiceProvider 的 GetServices()方法获取服务那么Scoped 服务的行为就和 Singleton 是一样的,它的的生命周期和 IServiceProvider 对象是一致的,下面的代码演示了如何使用 ScopedService,
//在using的作用域内scopeService是单例的
//在创建新的Scope之后,容器会创建新的scopedService实例
using (var scope = serviceProvider.CreateScope())
{var scopedServiceProvider = scope.ServiceProvider;var myScopedService = scopedServiceProvider.GetService<IMyScopedService>();
}
除了使用容器直接获取服务,我们还需要了解容器的注入方式,ioc容器的注入通常有三种方法
- 构造函数注入,在构造函数中将服务已参数的方式注入到类中。
- 方法注入,通过指定的方法将服务实例传入类中。
- 属性注入,通过设置实例到属性将服务实例注入到类中。DI 容器暂不支持该注入方式。
构造函数注入在上面已经演示了,下面是 http://ASP.NET Core 自定义Middleware 中方法注入的示例代码,
public class CustomMiddleware
{private readonly RequestDelegate _next;public CustomMiddleware(RequestDelegate next){_next = next;}//在Invoke方法中,将IMyScopedService服务注入到类中。public async Task Invoke(HttpContext httpContext, IMyScopedService svc){svc.MyProperty = 1000;await _next(httpContext);}
四、在 http://ASP.NET Core 中替换容器实现
DI 容器相对于其他第三方更加成熟的 IoC 容器来说,功能并不是十分完善,下面是 DI 容器暂时不支持的功能。
- 属性注入
- 基于名称的注入
- 子容器
- 自定义的生命周期管理
- 支持 Func 的延迟初始化
- 基于约定的注册
不过在 DI 容器能满足你需求的情况下,微软还是建议使用该容器。 如果它不能满足你的需求,你可以选择下面推荐的第三方 IoC 容器。
- Autofac
- DryIoc
- Grace
- LightInject
- Lamar
- Stashbox
- Unity
不过在 http://ASP.NET Core 中情况比较特殊,由于 http://ASP.NET Core 是基于 DI 容器的,所以要在http://ASP.NET Core 中使用其他容器,就需要替换 IServiceProvider 的实现。下面的代码展示的是如何在 http://ASP.NET Core 中集成 Autofac 容器。
public class Program
{public static void Main(string[] args){// 适用于ASP.NET Core 3.0+:var host = Host.CreateDefaultBuilder(args).UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureWebHostDefaults(webHostBuilder => {webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory()).UseIISIntegration().UseStartup<Startup>();}).Build();host.Run();}}相关文章:
Microsoft.Extensions 简介
Microsoft.Extensions 简介 一、Microsoft.Extensions 简介 .NET Extensions 是一套官方的、开源的、跨平台的 API 集合,提供了一些常用的编程模式和实用工具,例如依赖项注入、日志记录、缓存、Host以及配置等等。该项目的大多数 API 都被用在 .NET 平…...
k8s 金丝雀发布与声明式管理
Deployment控制器支持自定义控制更新过程中的滚动节奏,如“暂停(pause)”或“继续(resume)”更新操作。比如等待第一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后…...
百度Comate SaaS版本正式发布,助力开发者加速研发过程
百度Comate是基于文心大模型的智能代码助手,让开发者的编码更快、更好、更简单,为开发者自动生成完整的、且更符合实际研发场景的代码行或整个代码块,帮助每一位开发者轻松完成研发任务。10月17日召开的百度世界大会上,百度CTO王海…...
8类放球问题
放球问题简介 放球问题是一类很有意思的排列组合问题。通俗来说,就是把n个小球放到m个盒子里,问有几种放法。根据小球是否相同,盒子是否相同,是否允许有空盒,又可以把问题细分为8个具体的问题。其中有一些问题是非常简…...
【APP VTable】和市面上的 Table 组件一样,都是接收表格[] 以及数据源[]
博主:_LJaXi Or 東方幻想郷 专栏: uni-app | 小程序开发 开发工具:HBuilderX 这里写目录标题 表格组件USE 表格组件 <template><view class"scroll-table-wrapper"><view class"scroll-table-container"…...
深度学习 anaconda 安装问题
配置anaconda 在官网下载匹配版本的anaconda(官网下载可能时间比较长),可以选择清华镜像。 安装过程默认即可,或者根据情况进行修改。 旧版本是可以在安装的时候勾选添加路径到环境变量中的,但是我安装的是2023.9月…...
为什么现在学Rust编程是最好时机?
1.摘要 Rust是由Mozilla主导开发的通用、编译型编程语言。设计准则为:安全、并发、实用,支持函数式、并发式、过程式以及面向对象的编程风格。Rust的设计目标之一,是要使设计大型的互联网客户端和服务器的任务变得更容易,因此更加强调安全性、存储器配置以及并发处理等方面的特…...
Java——Spring的控制反转(一文详解IOC)
Spring,Spring MVC,Spring Boot 三者比较 答: 这三者专注的领域不同,解决的问题也不一样;总的来说,Spring 就像一个大家族,有众多衍生产品例如 Boot,Security,JPA等等。…...
Android Glide限定onlyRetrieveFromCache取内存缓存submit超时阻塞方式,Kotlin
Android Glide限定onlyRetrieveFromCache取内存缓存submit超时阻塞方式,Kotlin import android.os.Bundle import android.util.Log import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import com.b…...
tinymce输入框怎么限制只输入空格或者回车时不能提交
项目场景: 项目相关背景: tinymce输入框只输入空格或者回车时提交的空数据毫无意义,所以需要限制一下 无意义的输入: 解决方案: 因为tinymce输入框传到后端的数据是代码形式,所以不能直接.trem&#…...
时间、空间复杂度的例题详解
文章前言 上篇文章带大家认识了数据结构和算法的含义,以及理解了时间、空间复杂度,那么接下来来深入理解一下时间、空间复杂度。 时间复杂度实例 实例1 // 计算Func2的时间复杂度? void Func2(int N) {int count 0;for (int k 0; k <…...
Ubuntu22.04 搭建 OpenHarmony 命令行开发环境
文章目录 简介安装工具链获取gitee源码安装编译工具编译测试 简介 在本文中,我们将介绍如何使用命令行工具在你的设备上安装OpenHarmony操作系统。OpenHarmony是一个开源的、面向物联网(IoT)设备的操作系统,它提供了一套全面的开…...
10.27 知识总结(前端)
一、 前端 1.1 什么是前端? 前端是所有跟用户直接打交道的都可以称之为是前端 比如:PC页面、手机页面、平板页面、汽车显示屏、大屏幕展示出来的都是前端内容 通俗点就是能够用肉眼看到的都是“前端” 1.2 为什么要学前端 学了前端以后我们就可以做全栈工…...
操作系统(02326)考试题库
博客主页:https://tomcat.blog.csdn.net 博主昵称:农民工老王 主要领域:Java、Linux、K8S 期待大家的关注💖点赞👍收藏⭐留言💬 目录 单选题多选题主观题 单选题 把并发进程中与共享变量有关的程序段称为…...
LeetCode题:70爬楼梯,126斐波那契数
目录 70:爬楼梯 题目要求: 解题思路:(类似斐波那契数) 递归解法: 非递归解法: 126:斐波那契数 题目要求: 解题思路: 递归解法: 非递归解…...
VTK OrientationMarker 方向 三维坐标系 相机坐标轴 自定义坐标轴
本文 以 Python 语言开发 我们在做三维软件开发时,经常会用到相机坐标轴,来指示当前空间位置; 坐标轴效果: 相机方向坐标轴 Cube 正方体坐标轴 自定义坐标轴: Code: Axes def main():colors vtkNamedC…...
工控安全与网络安全有什么不同?
在当代,全球制造业正在经历一场前所未有的技术变革。工业4.0不仅代表着自动化和数据交换的进步,它还揭示了工业自动化、智能制造与系统集成的融合。这种集成为企业带来了效率和质量的双重提升,但同时也暴露出新的安全隐患。工控系统成为了这一…...
性能测试工具:Jmeter介绍
JMeter是一个开源的Java应用程序,由Apache软件基金会开发和维护,可用于性能测试、压力测试、接口测试等。 1. 原理 JMeter的基本原理是模拟多用户并发访问应用程序,通过发送HTTP请求或其他协议请求,并测量响应时间、吞吐量、并发…...
Golang Struct 继承的深入讨论和细节
1)结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段、方法,都可以使用。 type A struct {Name stringage int }func (a *A) SayName() {fmt.Println("A say name", a.Name) }func (a *A) s…...
Android11分区介绍
1.分区汇总 3566及3568分区对应如下: rockdev/Image-rk3566_rgo/ ├── boot.img ├── dtbo.img ├── MiniLoaderAll.bin ├── misc.img ├── parameter.txt ├── recovery.img ├── super.img ├── uboot.img └── vbmeta.img 2.分区说明 分区 说明 boo…...
从温控器到无人机:PID参数整定的‘手感’秘籍,附C语言代码避坑指南
从温控器到无人机:PID参数整定的‘手感’秘籍与实战避坑指南 在工业自动化和智能硬件开发中,PID控制算法就像一位隐形的调音师,默默调节着系统的每一个细微变化。无论是缓慢升温的工业烘箱,还是高速响应的四旋翼无人机,…...
Qwen3-14B推理速度实测:10核CPU+24GB显存下首token延迟<800ms
Qwen3-14B推理速度实测:10核CPU24GB显存下首token延迟<800ms 1. 测试环境与配置 1.1 硬件配置 本次测试使用的硬件配置完全匹配Qwen3-14B私有部署镜像的推荐规格: GPU:RTX 4090D 24GB显存(NVIDIA驱动550.90.07)…...
Asp.Net MVC杂谈之:—步步打造表单验证框架[重排版](1)
在实际使用中,我们可以考虑多种形式来进行这一验证(注:本文目前只研究服务器端验证的情况),最直接的方式莫过于对每个表单值手动用C#代码进行验证了,比如: if(!Int32.TryParse(Request.Form[“age”], out age)){ xxxx… } If(age < xxx || age > xxx){ xxxx… }…...
【Hung-yi Lee】《Introduction to Generative Artificial Intelligence》(6)
图片来自于 midjourney Introduction to Generative AI 2024 Spring 文章目录第11講:大型語言模型在「想」什麼呢? — 淺談大型語言模型的可解釋性(24.05.03)参考第11講:大型語言模型在「想」什麼呢? — 淺…...
图片去水印 API 接口实战:网站如何实现自动去水印(Python / PHP / C#)
在做网站或后台系统时,一个很常见但容易被忽视的问题是: 👉 用户上传的图片自带水印 👉 平台展示希望统一成干净版本 👉 还要支持批量、自动化处理 👉 最好能无缝接入现有系统 如果你正在找: …...
PMOS 在电源管理中的高效应用
1. PMOS在高侧开关中的天然优势 我第一次用PMOS做高侧开关是在一个车载设备项目里。当时需要控制12V电源的通断,尝试了几种方案后,发现PMOS简直是这个场景的"天选之子"。相比NMOS,PMOS最大的优势就是控制逻辑简单直接——栅极拉低导…...
用Asian Beauty Z-Image Turbo做古风头像:简单三步生成独一无二的东方美学作品
用Asian Beauty Z-Image Turbo做古风头像:简单三步生成独一无二的东方美学作品 想象一下,你的社交媒体头像不再是一张普通的自拍或卡通形象,而是一幅充满东方韵味的古风艺术作品——可能是唐代仕女的温婉,宋代文人的儒雅…...
CTF逆向实战:从RC4到Base64,手把手拆解CTFshow赛题
1. RC4加密实战:从文件分析到密钥破解 第一次接触CTF逆向题时,看到RC4加密可能会觉得无从下手。但实际拆解后你会发现,这类题目往往藏着明显的突破口。就拿CTFshow这道re2赛题来说,整个解题过程就像在玩解谜游戏。 用IDA打开题目…...
Spring AI vs Python生态:Java开发者如何选择AI工具链?
Spring AI vs Python生态:Java开发者如何构建高效AI工具链? 当Java开发者第一次踏入AI应用开发领域时,往往会面临一个灵魂拷问:是拥抱Python生态的LangChain/LlamaIndex,还是坚持Java技术栈选择Spring AI?这…...
Fish Speech 1.5开源可部署:模型权重分离存储与热更新机制设计
Fish Speech 1.5开源可部署:模型权重分离存储与热更新机制设计 1. 引言:语音合成的新突破 当你听到一段自然流畅的语音,是否曾想过它可能完全由AI生成?Fish Speech 1.5正是这样一个令人惊叹的技术成果——它能够仅凭10-30秒的参…...
