我在Azure Service Fabric中有一个无状态服务,并且我正在使用Microsoft.Extensions.DependencyInjection,尽管任何其他DI框架都存在相同的问题。在我的Program.cs中,我创建一个ServiceCollection,添加所有(除了一个)注册,创建服务提供程序,并将其传递给服务的构造函数。任何具有外部条目的服务方法都将创建一个新的服务范围并调用主业务逻辑类。问题是,我想成为作用域生存期的类之一需要一个值,该值是请求本身的输入参数。这是我想要实现的代码片段。
internal sealed class MyService : StatelessService, IMyService
{
private IServiceProvider _serviceProvider;
private IServiceScopeFactory _scopeFactory;
public MyService(StatelessServiceContext context, IServiceProvider serviceProvider)
: base(context)
{
_serviceProvider = serviceProvider;
_scopeFactory = _serviceProvider.GetRequiredService<IServiceScopeFactory>();
}
public async Task<MyResponse> ProcessAsync(MyRequest request, string correlationId, CancellationToken cancellationToken)
{
using (var scope = _scopeFactory.CreateScope())
{
var requestContext = new RequestContext(correlationId);
//IServiceCollection serviceCollection = ??;
//serviceCollection.AddScoped<RequestContext>(di => requestContext);
var businessLogic = scope.ServiceProvider.GetRequiredService<BusinessLogic>();
return await businessLogic.ProcessAsync(request, cancellationToken);
}
}
}
Run Code Online (Sandbox Code Playgroud)
取消令牌已经在所有地方传递,包括传递给不直接使用它的类,只是为了可以将其传递给使用它的依赖项,我想避免对请求上下文执行相同操作。
我的MVC API中存在相同的问题。我可以创建中间件,该中间件将从HTTP标头中提取相关ID,因此API控制器无需像服务结构服务那样处理它。我可以使其工作的一种方法是提供RequestContext
默认的构造函数,并具有可变的关联ID。但是,绝对重要的是在请求期间不更改相关ID,因此我真的很希望在上下文类中具有仅获取属性的安全性。
目前,我最好的想法是拥有一个具有SetCorrelationId方法的范围限定的RequestContextFactory,并且RequestContext注册只是调用工厂来获取实例。如果在设置ID之前请求了新实例,则工厂可以引发异常,以确保不创建无ID的上下文,但这并不是一个好的解决方案。
如何在依赖项注入框架中干净地注册只读对象,其中值取决于传入的请求?