依赖注入(Dependency Injection, DI)详细讲解 + 结合您项目的最佳实践完整代码
✅ 依赖注入Dependency Injection, DI详细讲解 结合您项目的最佳实践完整代码一、什么是依赖注入DI依赖注入是一种软件设计模式属于控制反转IoC的具体实现。核心思想不要在类内部自己创建依赖的对象而是通过外部容器把依赖“注入”进来。传统方式紧耦合publicclassMainBoardService{privateIStationRepository_reponewStationRepository();// 自己 new}DI 方式松耦合publicclassMainBoardService{privatereadonlyIStationRepository_repo;publicMainBoardService(IStationRepositoryrepo)// 通过构造函数注入{_reporepo;}}二、依赖注入的三大核心方式注入方式代码示例使用场景推荐程度构造函数注入推荐public XX(IYY yy)必须依赖、不可变★★★★★属性注入public IYY Yy { get; set; }可选依赖★★方法注入public void Init(IYY yy)临时使用或后期注入★三、依赖注入的重大优势松耦合类与类之间通过接口依赖便于替换实现。可测试性单元测试时可轻松注入 Mock 对象。可维护性修改实现不需要改动调用方。生命周期管理容器自动管理 Singleton、Scoped、Transient。并行开发团队成员可并行开发不同模块。配置集中所有依赖注册统一管理清晰可见。支持 AOP日志、事务、缓存等横切关注点。四、您项目中用到的两种容器Microsoft.Extensions.DependencyInjectionMS DI轻量、官方、性能好用于 EF Core。Prism.UnityWPF/Prism 框架的 IoC 容器用于 UI 层和服务解析。当前问题根源两种容器混合使用时必须做好“桥接”。五、优化后的完整代码推荐最终版本1.App.xaml.cs最重要// MaxWell/App.xaml.csusinglog4net;usingMaxWell.CommonBasis;usingMaxWell.Interface;usingMicrosoft.EntityFrameworkCore;usingMicrosoft.Extensions.DependencyInjection;usingPrism.Ioc;usingPrism.Unity;usingSystem;usingSystem.Threading;usingSystem.Threading.Tasks;usingSystem.Windows;namespaceMaxWell{publicpartialclassApp:PrismApplication{privateIServiceProvider_msServiceProvidernull!;// MS DI 容器publicApp(){AppDomain.CurrentDomain.UnhandledException(s,e)LogUnhandledException(e.ExceptionObjectasException,AppDomain);DispatcherUnhandledException(s,e)LogUnhandledException(e.Exception,Dispatcher);TaskScheduler.UnobservedTaskException(s,e)LogUnhandledException(e.Exception,TaskScheduler);}protectedoverrideWindowCreateShell()Container.ResolveMainWindow();protectedoverridevoidRegisterTypes(IContainerRegistrycontainerRegistry){// 1. 配置 Microsoft DI主要负责 EF Core 和仓储varservicesnewServiceCollection();ConfigureMicrosoftServices(services);_msServiceProviderservices.BuildServiceProvider();containerRegistry.RegisterInstance(_msServiceProvider);// 2. 桥接 MS DI 到 Prism 容器关键containerRegistry.RegisterSingletonIStationRepository(sp_msServiceProvider.GetRequiredServiceIStationRepository());// 3. Prism 容器注册UI 业务服务ConfigurePrismServices(containerRegistry);}privatevoidConfigureMicrosoftServices(IServiceCollectionservices){varconnectionStringData Sourcemaxwell.db;services.AddDbContextAppDbContext(optionsoptions.UseSqlite(connectionString),ServiceLifetime.Scoped);services.AddScopedIStationRepository,StationRepository();services.AddSingletonRepositoryFactory();}privatevoidConfigurePrismServices(IContainerRegistrycontainerRegistry){containerRegistry.RegisterSingletonIAlarmQueue,AlarmQueue();containerRegistry.RegisterSingletonStationManager();containerRegistry.RegisterSingletonIServiceFactory,ServiceFactory();// 视图与 ViewModelcontainerRegistry.RegisterForNavigationMainWindow,MainViewModel(MainWindow);}protectedoverrideasyncvoidOnInitialized(){base.OnInitialized();try{// 初始化数据库usingvarscope_msServiceProvider.CreateScope();vardbscope.ServiceProvider.GetRequiredServiceAppDbContext();awaitdb.Database.EnsureCreatedAsync();// 系统业务初始化awaitAppInitializer.InitializeAsync(Container);}catch(Exceptionex){MessageBox.Show($系统初始化失败{ex.Message}\n\n{ex},严重错误,MessageBoxButton.OK,MessageBoxImage.Error);Shutdown();}}protectedoverrideasyncvoidOnExit(ExitEventArgse){awaitAppInitializer.UninitializeAsync();(_msServiceProviderasIDisposable)?.Dispose();base.OnExit(e);}privatevoidLogUnhandledException(Exception?ex,stringsource){LogManager.GetLogger(GlobalException).Fatal($[{source}] 未捕获异常,ex);}}}2.ServiceFactory.cs// MaxWell.CommonBasis/ServiceFactory.csusingMaxWell.Common;usingMaxWell.Interface;usingMaxWell.Model;usingMaxWell.Service;namespaceMaxWell.CommonBasis{publicinterfaceIServiceFactory{IMainBoardServiceCreateMainBoardService(stringstationId,HardwareDevicehardwareDevice);IAuxCtrlServiceCreateAuxCtrlService(stringstationId,HardwareDevicehardwareDevice);ILoadMonitorServiceCreateLoadMonitorService(stringstationId,HardwareDevicehardwareDevice);IRFIDServiceCreateRFIDService(stringstationId,HardwareDevicehardwareDevice);IScannerServiceCreateScannerService(stringstationId,HardwareDevicehardwareDevice);}publicclassServiceFactory:IServiceFactory{privatereadonlyIStationRepository_repository;privatereadonlyIAlarmQueue_alarmQueue;// 构造函数注入推荐方式publicServiceFactory(IStationRepositoryrepository,IAlarmQueuealarmQueue){_repositoryrepository??thrownewArgumentNullException(nameof(repository));_alarmQueuealarmQueue??thrownewArgumentNullException(nameof(alarmQueue));}publicIMainBoardServiceCreateMainBoardService(stringstationId,HardwareDevicehardwareDevice)newMainBoardService(Registry.CreateDriver(hardwareDevice.DriverType??MainBoard,stationId),_repository,_alarmQueue,stationId,hardwareDevice);// 其他 Create 方法同理...publicIAuxCtrlServiceCreateAuxCtrlService(stringstationId,HardwareDevicehardwareDevice)newAuxCtrlBoardService(Registry.CreateDriver(hardwareDevice.DriverType??AuxPLC,stationId),_repository,_alarmQueue,stationId,hardwareDevice);publicILoadMonitorServiceCreateLoadMonitorService(stringstationId,HardwareDevicehardwareDevice)newLoadMonitorService(Registry.CreateDriver(hardwareDevice.DriverType??LoadMonitor,stationId),_repository,_alarmQueue,stationId,hardwareDevice);publicIRFIDServiceCreateRFIDService(stringstationId,HardwareDevicehardwareDevice)newRFIDService(Registry.CreateDriver(hardwareDevice.DriverType??RFID,stationId),_repository,_alarmQueue,stationId,hardwareDevice);publicIScannerServiceCreateScannerService(stringstationId,HardwareDevicehardwareDevice)newScannerService(Registry.CreateDriver(hardwareDevice.DriverType??Scanner,stationId),_repository,_alarmQueue,stationId,hardwareDevice);}}3.HardwareServiceBase.cs关键基类建议这样写publicabstractclassHardwareServiceBase:IHardwareService{protectedreadonlyIHardwareDriver_driver;protectedreadonlyIStationRepository_repository;protectedreadonlyIAlarmQueue_alarmQueue;protectedreadonlyILog_logger;protectedreadonlystringStationId;protectedreadonlystringServiceName;protectedHardwareServiceBase(IHardwareDriverdriver,IStationRepositoryrepository,IAlarmQueuealarmQueue,stringstationId,stringserviceName){_driverdriver??thrownewArgumentNullException(nameof(driver));_repositoryrepository??thrownewArgumentNullException(nameof(repository));_alarmQueuealarmQueue??thrownewArgumentNullException(nameof(alarmQueue));StationIdstationId;ServiceNameserviceName;_loggerLogManager.GetLogger($Service.{serviceName});}// ... 其他方法保持不变InitializeAsync、StartAsync 等}六、总结建议优先使用构造函数注入。接口编程所有服务都依赖接口而非具体类。避免 Service Locator 模式Container.Resolve滥用。生命周期选择Singleton全局唯一如StationManager、ServiceFactoryScoped每个请求/作用域一个如DbContext、仓储Transient每次都新创建

相关新闻

FISCO BCOS的落盘加密

FISCO BCOS的落盘加密

区块链部署是多方参与的,为了简化多方协作环境的搭建,通常会使用公有云部署区块链。机构将自己的节点部署到云上,让服务与云上的节点进行交互,实现多方协作。在这个架构中,机构内部的安全性是很高的,尤其是在金融机构。 虽然通过网络的隔离机制,将节点限制在“内网”中,…

2026/7/22 19:52:59 阅读更多 →
AI Brainstore如何实现AI记忆与学习:10个核心技术解析

AI Brainstore如何实现AI记忆与学习:10个核心技术解析

AI Brainstore如何实现AI记忆与学习:10个核心技术解析 【免费下载链接】ai-brainstore An experiment concept for an AI brain. 项目地址: https://gitcode.com/gh_mirrors/ai/ai-brainstore AI Brainstore是一个革命性的AI大脑实验项目,它为AI智…

2026/7/22 19:52:57 阅读更多 →
技术债务的量化、偿还与预防:从代码坏味道到架构腐化的度量与治理框架

技术债务的量化、偿还与预防:从代码坏味道到架构腐化的度量与治理框架

技术债务的量化、偿还与预防:从代码坏味道到架构腐化的度量与治理框架 一、技术债务的复利模型:为什么两周不清理的 TODO 会在三个月后让你加班到凌晨 技术债务(Technical Debt)本质上是一个复利成本模型。一条临时的 Workaround …

2026/7/22 19:52:55 阅读更多 →

最新新闻

银行卡二 / 三 / 四要素核验 API:原理、差异与业务选型指南

银行卡二 / 三 / 四要素核验 API:原理、差异与业务选型指南

线上业务只要涉及实名、绑卡、打款、提现,就绕不开银行卡要素核验。同样是校验,二要素、三要素、四要素 API 看似只是多填一个内容,实则在安全等级、适用场景上有所差距。企业选对接口,帮助客户办理业务会更加安全高效。 一、银行…

2026/7/23 21:06:49 阅读更多 →
ARM嵌入式外设寄存器详解:从内存映射到UART、SPI、USB实战

ARM嵌入式外设寄存器详解:从内存映射到UART、SPI、USB实战

1. 项目概述与寄存器核心概念 在嵌入式系统开发领域,尤其是基于ARM架构的微处理器单元(MPU)进行底层驱动开发时,与硬件外设的交互是绕不开的核心环节。这种交互并非直接操作物理引脚,而是通过一种称为“内存映射I/O”的…

2026/7/23 21:06:49 阅读更多 →
物联网智能锁落地实战:网约房/民宿人证核验+远程授权,解决安全与运营痛点

物联网智能锁落地实战:网约房/民宿人证核验+远程授权,解决安全与运营痛点

0 前言 随着全国文旅与公安监管体系持续收紧,网约房、分散式民宿正式进入强合规、重实名、轻人工、数字化的治理新阶段。相较于传统酒店,分散式短租房源存在点位分散、租客流动性大、无固定前台、人工运维成本高、监管溯源难等行业共性问题。 传统民宿依…

2026/7/23 21:06:49 阅读更多 →
告别低效加班!浩辰CAD看图王电脑版6大硬核功能,看图改图效率直接拉满

告别低效加班!浩辰CAD看图王电脑版6大硬核功能,看图改图效率直接拉满

经常和CAD图纸打交道的朋友,多半都有过这种糟心体验:统计门窗苗木数到眼酸,几十张图纸转PDF点到手指发麻,两版图纸对比全靠肉眼逐线找,半天下来进度没走多少,时间全耗在重复操作上。 浩辰CAD看图王电脑版没…

2026/7/23 21:06:49 阅读更多 →
Claude中转站技术文档生成:接口说明要能被执行

Claude中转站技术文档生成:接口说明要能被执行

技术文档常常在项目后期才补,接口已经能跑,说明却还不完整。Claude中转站 可以帮助整理接口说明、参数解释、错误码和 FAQ,但前提是资料来自真实接口。 这类场景虽然具体,但背后都涉及统一入口、流程拆分、记录归档和人工复核。只…

2026/7/23 21:06:48 阅读更多 →
AI技术提升SEO关键词的优化效果与应用方法

AI技术提升SEO关键词的优化效果与应用方法

本文探讨了AI技术在SEO重要词优化中的多种应用,呈现了其如何帮助提升重要词的效果。AI在重要词挖掘中,能够通过分析用户行为和搜索趋势,快速识别高效的相关重要词。同时,在竞争分析方面,AI可以深入洞察竞争对手的策略&…

2026/7/23 21:05:48 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻