C# 服务注册与生命周期

服务未注册与生命周期的区别与冲突问题

服务未注册指依赖注入容器中未找到所需服务的类型映射,通常抛出InvalidOperationException。生命周期冲突指服务注册时生命周期配置不一致(如单例依赖瞬态服务),导致资源泄露或状态异常。

服务未注册的解决方法

检查服务是否在Startup.cs或Program.cs中正确注册:

csharp 复制代码
// 正确注册示例
services.AddScoped<IMyService, MyService>();

使用TryAdd方法避免重复注册:

csharp 复制代码
services.TryAddScoped<IMyService, MyService>();

生命周期冲突的解决方法

避免单例服务依赖瞬态/作用域服务:

csharp 复制代码
// 错误示例(单例依赖瞬态)
services.AddSingleton<SingletonService>();
services.AddTransient<TransientService>(); // 被单例引用会导致问题

// 正确做法:统一生命周期
services.AddSingleton<SingletonService>();
services.AddSingleton<DependencyService>();

使用工厂模式延迟解析:

csharp 复制代码
services.AddSingleton<IService>(provider => 
    provider.GetRequiredService<IOtherService>().CreateService());

验证服务注册的代码示例

通过ServiceProvider手动验证:

csharp 复制代码
var serviceProvider = services.BuildServiceProvider();
using var scope = serviceProvider.CreateScope();
var service = scope.ServiceProvider.GetService<IMyService>();
if (service == null) throw new Exception("Service not registered");

生命周期冲突检测工具

启用依赖验证(开发环境):

csharp 复制代码
services.BuildServiceProvider(validateScopes: true);

ASP.NET Core默认在开发环境开启范围验证,可通过以下配置强化检测:

csharp 复制代码
services.BuildServiceProvider(new ServiceProviderOptions {
    ValidateScopes = true,
    ValidateOnBuild = true
});
相关推荐
冻柠檬飞冰走茶3 小时前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
FRing033 小时前
vue2干货总结7(自定义指令、插槽、单页应用程序、路由的使用(VueRouter))
开发语言·前端·vue.js·vue2
雪落漂泊3 小时前
C++算法 二分查找篇(上)
开发语言·c++·算法
波力海苔夹心脆6754 小时前
C# WPF 资源字典详解:ResourceDictionary、MergedDictionaries 与自定义控件案例
开发语言·c#·wpf·入门教程·resource·资源字典
不会算法的笨小孩5 小时前
异常的使用以及会出现的问题
开发语言·c++·c++11·异常
AI导出鸭PC端6 小时前
Perplexity批量导出没有PDF模式?AI导出鸭插件补上最后一块拼图
人工智能·pdf·c#·ai导出鸭
csdn_aspnet7 小时前
Redis 入门:Windows、Mac安装指南
数据库·windows·redis·缓存·mac
Hhy_11077 小时前
《C++深度解构06》手撕 string —— 从底层内存管理到深浅拷贝彻底吃透
c语言·开发语言·c++·学习·visual studio
starzy19907 小时前
深入理解Scala函数定义:从方法到函数的类型跨越
开发语言·scala
starzy19907 小时前
深入理解Scala递归函数:从栈溢出到尾调用优化
开发语言·scala