我想更改请求范围的服务或在自定义中间件层中设置一个。
具体来说,我希望能够在Startup.cs
中执行类似下面的设计示例:
public void ConfigureServices(IServiceCollection service)
{
service.AddScoped<IMyUserDependentService>((provider) => {
return new MyService());
});
}
public void Configure(...) {
//other config removed
app.Use(async (context, next) => {
var myService = context.ApplicationServices.GetService<IMyUserDependentService>();
myService.SetUser(context.User.Identity.Name);//Name is Fred
next.Invoke();
});
}
然后在控制器中执行以下操作:
public class HomeController: Controller
{
public HomeController(IMyUserDependentService myService)
{
//myService.UserName should equal Fred
}
}
问题是,这不起作用。 myService.UserName在控制器中不是Fred,它是null。我认为IOC容器正在控制器中创建一个新实例,而不是使用中间件中的一个。
如果我将服务范围更改为Transient,Fred会被记住,但这并不会有帮助,因为该服务取决于当前用户是谁。
总结一下,我需要的是创建/或编辑需要当前用户(或其他当前请求变量)的服务,但我无法解决这个问题。
提前致谢!
答案 0 :(得分:4)
您是否尝试过使用context.RequestServices
?
答案 1 :(得分:0)
我遇到了类似的问题,出现了类似的错误
InvalidOperationException: Cannot resolve scoped service 'IScopedService' from root provider.
,引发的异常情况没有得到很好的记录。
这是我解决的方法:
[Startup.cs]
services.AddScoped<IAnyScopedService, AnyScopedService>();
services.AddSingleton<ISomeOtherSingletonService, SomeOtherSingletonService>();
[MyMiddleware.cs]
public sealed class MyMiddleware
{
private readonly RequestDelegate _next;
private readonly ISomeOtherSingletonService _Svc;
public MyMiddleware(
RequestDelegate next,
ISomeOtherSingletonService svc)
{
_next = next;
_Svc = svc;
}
public async Task Invoke(HttpContext context,
IAnyScopedService scopedService)
{
// Some work with scoped service
}
}
实际上,中间件仅被实例化一次,但是被调用了很多次。 因此,构造函数采用单例实例,在该实例中invoke方法可以获取作用域内注入的参数。
有关Mark Vincze post的详细信息