c# 如何实现依赖注入容器

发布时间 - 2025-12-27 00:00:00    点击率:
.NET 内置依赖注入容器是 IServiceCollection + IServiceProvider,原生支持、无需额外安装,仅提供构造函数注入和 Transient/Scoped/Singleton 生命周期管理。

什么是 .NET 内置的依赖注入容器 .NET 从 Core 开始就内置了轻量级 DI 容器,类型是 IServiceCollection + IServiceProvider,它不是第三方库(比如 Autofac 或 DryIoc),而是框架原生支持的抽象层。你不需要额外安装包(Microsoft.Extensions.DependencyInjectionMicrosoft.NET.Sdk 项目中默认引用)。

它的定位是“够用、安全、与 Host 集成好”,不追求高级特性(如属性注入、装饰器、命名注册)。如果你只需要构造函数注入 + 生命周期管理(Transient / Scoped / Singleton),它完全胜任。

如何注册服务并获取实例 注册靠 IServiceCollection 扩展方法,解析靠 IServiceProviderGetService()GetRequiredService()
  • AddTransient():每次请求都新建实例
  • AddScoped():每个作用域(如一次 HTTP 请求)内复用同一个实例
  • AddSingleton():整个应用生命周期只创建一次
var services = new ServiceCollection();
services.AddTransient();
services.AddScoped();
services.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();

原因:

  • 手动 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, Handler>() ❌ 编译失败 —— C# 不允许泛型类型参数在泛型方法调用中作为实参直接出现

复杂对象图或需要 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在项目中的应用  如何在阿里云通过域名搭建网站?