.NET Core服务项目中工厂模式DI下ServiceProvider返回空的问题
问题原因分析
- 核心问题是Scoped服务生命周期与根服务提供者不兼容:你将
Cube和Sphere注册为Scoped生命周期服务,但ShapeFactory注入的是根容器的IServiceProvider,直接通过根容器获取Scoped服务会返回null(根容器无法解析Scoped服务,必须在创建的服务作用域内获取)。 - 代码中缺少
ShapeEnum的定义,虽不是当前返回null的直接原因,但会导致编译错误,需补充。
修正方案
1. 补充ShapeEnum定义
在项目中添加枚举类:
public enum ShapeEnum { Cube, Sphere }
2. 调整服务解析逻辑(二选一)
方案一:将Shape生命周期改为Transient
你的场景中每次计算都需要新实例,Transient更适配,修改Program.cs中的注册代码:
services.AddTransient<Sphere>().AddTransient<IShape, Sphere>(s => s.GetService<Sphere>()); services.AddTransient<Cube>().AddTransient<IShape, Cube>(s => s.GetService<Cube>());
修改后根容器可直接解析Transient服务,ShapeFactory中的GetService能正常返回实例。
方案二:保持Scoped生命周期,在Factory中创建服务作用域
若必须使用Scoped,修改ShapeFactory,在获取服务时创建作用域:
public class ShapeFactory : IShapeFactory { private readonly IServiceProvider serviceProvider; public ShapeFactory(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; } public IShape GetShape(ShapeEnum shapeEnum) { using var scope = serviceProvider.CreateScope(); var scopedProvider = scope.ServiceProvider; switch (shapeEnum) { case ShapeEnum.Cube: return scopedProvider.GetRequiredService<Cube>(); case ShapeEnum.Sphere: return scopedProvider.GetRequiredService<Sphere>(); default: throw new ArgumentOutOfRangeException(nameof(shapeEnum), shapeEnum, $"Shape of {shapeEnum} is not supported."); } } }
建议使用GetRequiredService替代GetService,服务不存在时会直接抛出异常,便于调试。
3. 优化Worker执行逻辑(可选)
当前Worker会每秒重复执行计算,可调整为单次执行:
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { shapeCalculationService.CalculateShapeMeasurements(); _logger.LogInformation("Shape calculation completed at: {time}", DateTimeOffset.Now); // 保持服务运行直到收到取消信号 await stoppingToken.WaitHandle.WaitOneAsync(); }
内容的提问来源于stack exchange,提问作者Szelitzky Tibor
相关产品推荐
相关产品推荐

