.NET Minimal API单例服务每次请求重建问题及Windows服务托管咨询
一、单例SquareService重复重建的问题
这不是Minimal API的特性导致的,核心原因是DI容器中IAsyncRequestHandler<LocationByNameRequest, LocationResponse>接口的注册生命周期与SquareService不一致。
你仅注册了SquareService为单例,但注入的是接口类型,而AddMessagePipe()默认会自动为请求处理器接口注册瞬态实例,覆盖了你的单例设置。解决步骤:
- 修改服务注册代码,明确将接口与实现类绑定为单例:
builder.Services.AddMessagePipe(); // 同时注册接口和实现类为单例,确保容器解析接口时返回同一个实例 builder.Services.AddSingleton<IAsyncRequestHandler<LocationByNameRequest, LocationResponse>, SquareService>(); // 若仍需单独注册SquareService实例,可保留但非必须,上面的注册已包含实现类的单例 // builder.Services.AddSingleton<SquareService>();
- 验证实例唯一性:确保
SquareService中的GUID是在构造函数中初始化的只读字段,避免误判:
public class SquareService : IAsyncRequestHandler<LocationByNameRequest, LocationResponse> { private readonly Guid _instanceId = Guid.NewGuid(); public SquareService() { Console.WriteLine($"SquareService instance created: {_instanceId}"); } // 实现接口方法... }
二、Windows服务托管RESTful API的其他可行方案
除了Minimal API,还有以下几种成熟方案:
ASP.NET Core Web App直接转为Windows服务
这是官方推荐的方式,无需额外模板。只需在项目中添加Microsoft.Extensions.Hosting.WindowsServices包,然后在Program.cs中配置:var builder = WebApplication.CreateBuilder(args); // 配置为Windows服务 builder.Host.UseWindowsService(); // 后续添加服务、配置路由等发布后用
sc create命令注册为Windows服务即可。Worker Service + 自托管API
若需要在后台服务中同时运行其他任务(如定时任务),可使用Worker Service模板,集成ASP.NET Core的WebHost:public class Worker : BackgroundService { private readonly IWebHost _webHost; public Worker(IWebHost webHost) { _webHost = webHost; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await _webHost.RunAsync(stoppingToken); } }在
Program.cs中同时配置Worker和WebHost。使用TopShelf库
第三方开源库,简化Windows服务的创建、配置和部署,无需编写复杂的服务注册代码。通过NuGet安装TopShelf后,直接在主程序中定义服务逻辑:HostFactory.Run(x => { x.Service<MyService>(s => { s.ConstructUsing(name => new MyService()); s.WhenStarted(tc => tc.Start()); s.WhenStopped(tc => tc.Stop()); }); x.RunAsLocalSystem(); x.SetServiceName("MyRestService"); });发布后直接运行exe即可安装为服务。
传统WCF REST服务
若需要兼容旧系统,可使用WCF创建RESTful服务,通过WebHttpBinding配置,然后托管为Windows服务。但此方案已逐步被ASP.NET Core替代,仅推荐用于遗留系统场景。
内容的提问来源于stack exchange,提问作者bakerBite

