c# 如何实现依赖注入容器
发布时间 - 2025-12-27 00:00:00 点击率:次.NET 内置依赖注入容器是 IServiceCollection + IServiceProvider,原生支持、无需额外安装,仅提供构造函数注入和 Transient/Scoped/Singleton 生命周期管理。
什么是 .NET 内置的依赖注入容器
.NET 从 Core 开始就内置了轻量级 DI 容器,类型是 IServiceCollection + IServiceProvider,它不是第三方库(比如 Autofac 或 DryIoc),而是框架原生支持的抽象层。你不需要额外安装包(Microsoft.Extensions.DependencyInjection 在 Microsoft.NET.Sdk 项目中默认引用)。
它的定位是“够用、安全、与 Host 集成好”,不追求高级特性(如属性注入、装饰器、命名注册)。如果你只需要构造函数注入 + 生命周期管理(Transient / Scoped / Singleton),它完全胜任。
如何注册服务并获取实例
注册靠 IServiceCollection 扩展方法,解析靠 IServiceProvider 的 GetService() 或 GetRequiredService() :
-
AddTransi
ent() :每次请求都新建实例
-
AddScoped() :每个作用域(如一次 HTTP 请求)内复用同一个实例
-
AddSingleton() :整个应用生命周期只创建一次
var services = new ServiceCollection();
services.AddTransient();
services.AddScoped();
services.AddSingleton();
var provider = services.BuildServiceProvider();
// 使用
var userService = provider.GetRequiredService();
AddTransi
ent() :每次请求都新建实例AddScoped() :每个作用域(如一次 HTTP 请求)内复用同一个实例AddSingleton() :整个应用生命周期只创建一次var provider = services.BuildServiceProvider();
// 使用
var userService = provider.GetRequiredService
注意:GetService 返回 null 表示未注册;GetRequiredService 抛出 InvalidOperationException(更推荐,避免空引用)。
为什么在 Program.cs 中用 CreateHostBuilder 而不是手动 new ServiceCollection
在 Web 项目(.NET 6+)中,你不该手动构建 IServiceProvider,而应通过 Host.CreateDefaultBuilder() 或 WebApplicationBuilder 注入服务:
var builder = WebApplication.CreateBuilder(args);
// 注册服务(自动使用内置容器)
builder.Services.AddTransient();
builder.Services.AddHttpClient();
var app = builder.Build();
// 注册服务(自动使用内置容器)
builder.Services.AddTransient
var app = builder.Build();
原因:
- 手动
BuildServiceProvider()会提前触发容器构建,导致中间件、配置、日志等尚未注入 - Host 会帮你处理作用域生命周期(比如
HttpContext绑定Scoped服务) - 第三方扩展(如 EF Core、MediatR)依赖 Host 的服务发现机制
容易踩的坑:循环依赖和泛型注册
循环依赖在编译期不报错,运行时首次解析时抛出 InvalidOperationException: A circular dependency was detected。典型场景是 A 依赖 B,B 又依赖 A(包括间接依赖)。
泛型注册要注意闭合类型 vs 开放泛型:
services.AddTransient(typeof(IHandler ✅ 支持开放泛型映射-
services.AddTransient✅ 显式注册闭合类型, OrderCreatedHandler>(); - 但
services.AddTransient❌ 编译失败 —— C# 不允许泛型类型参数在泛型方法调用中作为实参直接出现, Handler >()
复杂对象图或需要 AOP/装饰器时,内置容器能力很快见顶。这时候才该考虑引入 Autofac 并替换默认容器 —— 但先确认是不是真需要,别一上来就上重武器。
# js
# json
# app
# microsoft
# c#
# 作用域
# .net
# 为什么
# red
# 中间件
# NULL
# 构造函数
# 循环
# 泛型
# 实参
# 对象
# typeof
# http
# 第三方
# 抛出
# 首次
# 帮你
# 你不
# 要注意
# 未注册
# 报错
# 绑定
# 就上
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
黑客入侵网站服务器的常见手法有哪些?
Laravel如何从数据库删除数据_Laravel destroy和delete方法区别
Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】
Laravel如何与Inertia.js和Vue/React构建现代单页应用
Laravel如何实现API速率限制?(Rate Limiting教程)
如何在万网ECS上快速搭建专属网站?
香港服务器部署网站为何提示未备案?
企业网站制作这些问题要关注
如何将凡科建站内容保存为本地文件?
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
如何在不使用负向后查找的情况下匹配特定条件前的换行符
Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】
Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
百度输入法ai组件怎么删除 百度输入法ai组件移除工具
Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】
如何自定义建站之星模板颜色并下载新样式?
Laravel项目怎么部署到Linux_Laravel Nginx配置详解
Laravel如何创建自定义Facades?(详细步骤)
Python制作简易注册登录系统
网站制作壁纸教程视频,电脑壁纸网站?
Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧
Android GridView 滑动条设置一直显示状态(推荐)
Laravel如何使用查询构建器?(Query Builder高级用法)
Python结构化数据采集_字段抽取解析【教程】
活动邀请函制作网站有哪些,活动邀请函文案?
微信公众帐号开发教程之图文消息全攻略
Laravel如何处理文件下载请求?(Response示例)
Swift开发中switch语句值绑定模式
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程
Laravel如何实现密码重置功能_Laravel密码找回与重置流程
Laravel PHP版本要求一览_Laravel各版本环境要求对照
PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)
laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法
Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】
如何在云主机上快速搭建多站点网站?
武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?
如何快速生成可下载的建站源码工具?
非常酷的网站设计制作软件,酷培ai教育官方网站?
Linux系统命令中tree命令详解
如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)
Laravel Debugbar怎么安装_Laravel调试工具栏配置指南
用v-html解决Vue.js渲染中html标签不被解析的问题
Laravel用户密码怎么加密_Laravel Hash门面使用教程
HTML 中动态设置元素 name 属性的正确语法详解
如何快速完成中国万网建站详细流程?
宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法
浅谈redis在项目中的应用
如何在阿里云通过域名搭建网站?
下一篇:Pulsar中间件入门学习
下一篇:Pulsar中间件入门学习


ent