首页/新闻资讯/正文详情

《C# 上位机开发(七):告别“牵一发而动全身”,图解 .NET 8 依赖注入(DI)与生命周期》

发布时间:2026/11/4 16:30:13 来源:云帆数科 栏目:资讯中心
《C# 上位机开发(七):告别“牵一发而动全身”,图解 .NET 8 依赖注入(DI)与生命周期》
在上一篇关于 MVVM 的文章中我们把 View 和 Model 解耦了。但在实际开发中还有一个更大的痛点类与类之间的强耦合。如果你在写代码时每次用到别的对象就直接new一个一旦项目变大你的代码就会变成一团乱麻。为了解决这个问题现代软件开发引进了依赖注入DI和控制反转IoC。今天我用最通俗的“新能源电车”的例子带你把这两个面试必考的概念彻底搞懂。1. 什么是依赖注入DI我们先把这个词拆开依赖、注入、依赖注入。1.1 什么是依赖如果类 A 离不开类 B我们就说 A 依赖 B。比如一辆新能源电车离不开电池。那么电车类就依赖电池类。// 电池类 public class Battery { } // 汽车类 public class Car { // 痛点Car 里面直接 new 了 Battery这叫强耦合。 // 如果哪天电池要加参数Car 类也得跟着改。 private Battery _battery new Battery(); }1.2什么是注入注入通俗地说就是“把外部的东西塞进来”。我们在写构造函数时不自己new对象而是要求外部把对象当成参数传进来。public class A { public A(object B) { // 这里的 B 就是外部“注入”进来的 } } public static void Main() { object b new object(); // 把 b 注入到 A 里面 A a new A(b); }1.3现在那依赖注入的意思也呼之欲出把 1.1 和 1.2 结合起来我不在内部new电池了而是在造汽车的时候把电池通过构造函数塞进去。同时为了更彻底地解耦我们通常会引入接口。汽车不依赖具体的“某品牌电池”而是依赖“电池的通用接口”。// 1. 定义电池接口解耦具体实现 public interface IBattery { } public class BatteryA : IBattery { } public class BatteryB : IBattery { } // 2. 汽车类依赖接口不依赖具体类 public class Car { private IBattery _battery; //通过构造函数注入依赖 public Car(IBattery battery) { _battery battery; } } // 实际使用时 // Car myCar new Car(new BatteryA()); // 想用A电池就传A看到上面的代码你可能就好奇了“参数怎么凭空生成了如果每次用都要在Main里面自己手动new一个电池传进去那我不还是得自己管理这些对象吗”。实则不然。在大型项目里这背后有一个管家——DI 容器也叫 IoC 容器。我们不再手动new对象而是告诉大管家“我要造一辆车你自己看着办。”大管家接管了对象的创建权这个权力转移的过程就叫控制反转IoC, Inversion of Control。2.控制反转容器IoC Container在现代 .NET如 .NET 8中官方自带了 DI 容器。它的使用分为两步注册Register简单讲就是创建一份制造清单解析Resolve简单讲就是根据制造清单制造我们想要的东西using Microsoft.Extensions.DependencyInjection; // 需要 NuGet 引入 public static void Main() { // 1. 创建服务集合准备一个流水线 var services new ServiceCollection(); // 2. 注册告诉流水线怎么造零件 // 告诉容器如果有人要 IBattery你就给他 new 一个 BatteryA services.AddTransientIBattery, BatteryA(); services.AddTransientCar(); // 3. 解析构建管家并向管家要车 var provider services.BuildServiceProvider(); // 我们只要 Car容器会自动把 BatteryA 塞进去 var car provider.GetRequiredServiceCar(); }底层原理反射Reflection的降维打击你可能会想容器凭什么能自动推导、无需选择、顺藤摸瓜因为 .NET 容器在底层使用了反射Reflection。当你执行GetRequiredServiceCar()时容器偷偷看了Car的构造函数发现它需要一个IBattery。于是它立刻去登记表里找IBattery的注册记录把BatteryA实例化并塞进去。哪怕依赖嵌套了十层比如 Car 依赖 BatteryBattery 依赖电芯它都能一层层顺藤摸瓜自动按顺序造好。3. 容器的三大生命周期在注册时我们用了AddTransient。其实 .NET 还提供了另外两个非常重要的生命周期方法它们决定了“对象能活多久”AddTransient瞬态每次向容器要它都给你new一个新的。适合用完就扔的临时工具。AddSingleton单例整个程序从启动到关闭只new一次。以后谁要都给同一个对象。AddScoped作用域在特定范围内是单例Web 开发常用上位机很少用。注意在我的上位机项目中负责 SQLite 持久化的SqliteRepository包含了长连接和后台消费者线程。这里必须注册为AddSingleton如果用了AddTransient每次切模式都创建一个新实例你的程序瞬间会打开几十个数据库连接直接死锁崩溃。4. 应用到 WPF 中App.xaml.cs理论说完了在 WPF 项目里我们通常把这个管家建在程序的入口处public partial class App : Application { public static IServiceProvider ServiceProvider { get; private set; } protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var services new ServiceCollection(); // 注册长连接单例 services.AddSingletonSqliteRepository(); // 注册主界面和 VM services.AddSingletonMainViewModel(); services.AddSingletonMainWindow(); ServiceProvider services.BuildServiceProvider(); // 解析主界面并展示 var mainWindow ServiceProvider.GetRequiredServiceMainWindow(); mainWindow.Show(); } }一句话概括依赖注入就是“我不造我只用”。以前你得自己跑去买零件组装汽车现在你只需要写个清单把脏活累活丢给大管家DI 容器它自然会完美的汽车送到你手上。3.完整代码新建标签页https://gitee.com/rebel-z/simple-hmi

相关推荐

论文理解【LLM-OR】——【OptiCycle/OptiState】Harnessing Language Models as Optimization Modeling Agents
论文理解【LLM-OR】——【OptiCycle/OptiState】Harnessing Language Models as Optimization Modeling Agents

本文初稿使用 PaperReading-skill 生成。给定论文标题、链接、arXiv/OpenReview 页面、DOI 或本地 PDF,让 Codex 自动完成论文检索、PDF 下载、图表抽取、代码仓库分析,并生成一份适合 Typora 阅读和后续整理的中文论文解读 Markdown 和 PDF,欢迎试用! 前往我的博客阅读本文… · 2026/11/4 16:30:13

官方 VS Code 扩展在第三方市场被植入后门?一份自查清理清单
官方 VS Code 扩展在第三方市场被植入后门?一份自查清理清单

文章目录 📖 介绍 📖 🏡 演示环境 🏡 📒 装了个「官方」扩展,背后却悄悄开了后门? 📒 🧭 事件经过:恶意代码藏在哪里 🔍 它到底动了什么:四步攻击链 🧪 怎么判断自己中没中:四张自查表 🛡️ 中招了怎么清理:别只卸载扩展 🎯 这件事给我们的提醒 ⚓… · 2026/11/4 16:29:12

中小学用车:家校通解决的是交接责任,不是车
中小学用车:家校通解决的是交接责任,不是车

中小学用车:家校通解决的是交接责任,不是车 孩子上车之后那几分钟,家长真正想知道的不是“车在哪”,而是“他到了没、谁接的”。 这两件事不一样。实时定位告诉你车在什么位置;交接记录告诉你孩子在几点几分被谁交到了… · 2026/11/4 16:28:11

基于ADALM-Pluto的GPS信号模拟器:C语言实现与实战避坑指南
基于ADALM-Pluto的GPS信号模拟器:C语言实现与实战避坑指南

简介:面向GPS信号模拟与软件定义无线电学习者的PLUTO-GPS-SIM工程源码包,用于生成GPS基带信号IQ数据流,并借助ADALM-Pluto SDR在GPS L1频点发射。用户可通过命令行设定静态位置,结合每日广播星历文件推算可见卫星的伪距与多普勒&a… · 2026/11/4 17:12:05

Linux内核防火墙设计与性能优化实践
Linux内核防火墙设计与性能优化实践

1. Linux内核防火墙概述作为一名长期从事Linux内核网络开发的工程师,我经常需要处理高性能网络过滤的需求。传统用户态防火墙(如iptables)虽然功能强大,但在处理高吞吐量网络流量时,用户态与内核态的频繁切换会成为性能… · 2026/11/4 17:12:05

Unreal Engine 5构建魔法世界:从场景优化到AI设计
Unreal Engine 5构建魔法世界:从场景优化到AI设计

1. 项目概述:解密"harrypotter08-1"的魔法世界构建逻辑这个看似简单的字符串背后隐藏着完整的魔法世界数字建模体系。作为从业十余年的奇幻题材开发者,我第一眼就意识到"harrypotter08-1"极可能是某位开发者对《哈利波特》系列第八章… · 2026/11/4 17:12:05

Nginx三种安装方式怎么选:包管理器、源码编译与容器部署
Nginx三种安装方式怎么选:包管理器、源码编译与容器部署

1. 先把选型这件事聊透:三种装法各自站在什么位置 我见过太多次这样的场景:一台新机器,需求是"装个 Nginx 做个入口转发",结果有人敲了一行 apt install nginx 就交付了,三天后业务方要上 HTTP/2、要加一个… · 2026/11/4 17:12:05

生命科学数字化转型:AI与云计算的合规高性能架构
生命科学数字化转型:AI与云计算的合规高性能架构

1. 生命科学企业的数字化转型浪潮过去三年间,全球TOP20药企在IT基础设施上的年均投入增长达到37%,其中AI算力支出占比从2019年的12%飙升至2022年的48%。这个数字背后,是冷冻电镜图像分析、分子动力学模拟、临床试验数据挖掘等场景对高性能计算… · 2026/11/4 17:12:05

Anaconda误删恢复与数据科学环境保护指南
Anaconda误删恢复与数据科学环境保护指南

1. 误删Anaconda的常见场景与影响评估那天下午我正在清理磁盘空间,手滑把整个anaconda3目录给rm -rf了。等反应过来时终端已经无情地返回了命令执行成功的提示符——这大概是我今年最昂贵的误操作之一。Anaconda作为Python数据科学生态的核心枢纽,其目录… · 2026/11/4 17:11:03

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

AI辅助技术栈评估:提升研发决策效率60%
AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17

从生成Token到直接决策:Jev如何重塑AI Agent工程实践
从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17

32G统一内存跑大模型:内存账、TPS实测与端云分流
32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码