ASP.NET Core 9中FastEndpoints端点内部调用方法咨询
在FastEndpoints中实现端点内部调用的正确方式
核心方案:使用IEndpointInvoker内置服务
FastEndpoints专门提供了IEndpointInvoker接口用于应用内部直接调用端点,它会自动处理依赖注入解析、HttpContext上下文传递,完美解决你遇到的三个问题。
具体实现步骤
注入
IEndpointInvoker到目标服务
在需要调用端点的服务中,通过构造函数注入该接口:public class MyService { private readonly IEndpointInvoker _endpointInvoker; public MyService(IEndpointInvoker endpointInvoker) { _endpointInvoker = endpointInvoker; } public async Task<MyResponse> InvokeMyEndpointAsync(MyRequest request) { // 调用指定端点并获取响应结果 var invokeResult = await _endpointInvoker.ExecuteAsync<MyEndpoint, MyRequest, MyResponse>(request); return invokeResult.Response; } }确保端点正常注册
你的端点需继承Endpoint<Req, Res>基类,且已通过app.MapFastEndpoints()完成自动注册,无需手动添加AddScoped<MyEndpoint>():public class MyEndpoint : Endpoint<MyRequest, MyResponse> { private readonly ILogger<MyEndpoint> _logger; public MyEndpoint(ILogger<MyEndpoint> logger) { _logger = logger; } public override void Configure() { Post("/api/my-endpoint"); AllowAnonymous(); } public override async Task HandleAsync(MyRequest req, CancellationToken ct) { _logger.LogInformation("处理请求:{Name}", req.Name); await SendAsync(new MyResponse { Message = $"Hello, {req.Name}!" }); } }后台场景的HttpContext处理(可选)
如果是在无请求上下文的后台服务中调用,可手动构建HttpContext并传入:// 从DI容器获取服务提供者 using var scope = serviceProvider.CreateScope(); var httpContext = new DefaultHttpContext { RequestServices = scope.ServiceProvider }; var invokeResult = await _endpointInvoker.ExecuteAsync<MyEndpoint, MyRequest, MyResponse>(request, httpContext);
方案优势
- 无需手动注入端点的全部依赖:
IEndpointInvoker会通过DI容器自动解析所有所需服务 - 自动维护HttpContext上下文:在请求链路中调用时自动传递当前上下文,后台场景可手动构建
- 完全遵循DI生命周期管理:避免手动实例化服务带来的资源泄漏风险
推荐最佳实践:提取业务逻辑到单独服务
如果你的业务逻辑需要被多个组件复用,更合理的方式是将端点的核心逻辑抽离到独立的业务服务中,端点仅负责请求接收、参数校验和响应返回,其他服务直接调用业务服务即可:
// 业务逻辑服务 public class UserGreetingService { private readonly ILogger<UserGreetingService> _logger; public UserGreetingService(ILogger<UserGreetingService> logger) { _logger = logger; } public async Task<string> GenerateGreetingAsync(string userName) { _logger.LogInformation("生成问候语:{UserName}", userName); await Task.Delay(100); // 模拟业务操作 return $"Hello, {userName}!"; } } // 端点类 public class MyEndpoint : Endpoint<MyRequest, MyResponse> { private readonly UserGreetingService _greetingService; public MyEndpoint(UserGreetingService greetingService) { _greetingService = greetingService; } public override void Configure() { Post("/api/my-endpoint"); AllowAnonymous(); } public override async Task HandleAsync(MyRequest req, CancellationToken ct) { var greeting = await _greetingService.GenerateGreetingAsync(req.Name); await SendAsync(new MyResponse { Message = greeting }); } } // 其他调用服务 public class MyService { private readonly UserGreetingService _greetingService; public MyService(UserGreetingService greetingService) { _greetingService = greetingService; } public async Task<MyResponse> GetGreetingAsync(string userName) { var greeting = await _greetingService.GenerateGreetingAsync(userName); return new MyResponse { Message = greeting }; } }
这种方式符合单一职责原则,代码复用性更强,同时避免了端点调用带来的上下文依赖问题。
内容的提问来源于stack exchange,提问作者nonsensation
相关产品推荐
相关产品推荐

