带有 DelegatingHandler 的 IHttpClientBuilder 在 Blazor web assembly 中创建额外的范围

问题描述 投票:0回答:1

我有以下情况:

builder.Services.AddHttpClient...
    .AddHttpMessageHandler<CustomMessageHandler>();

builder.Services.AddScoped<ScopedService>();

此作用域服务被注入到消息处理程序和页面代码中。 我的问题是对象不一样。有两个独立的作用域和两个独立的 ScopedService 实例。

第一个也是最明显的解决方案是将服务作为单例注入。 在工作解决方案时,这是不行的,因为许多服务或库都有“AddSomething”,其后面有“AddScoped”。

我发现的第二个解决方案是推荐 SuppressHandlerScope: https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.http.httpclientfactoryoptions.suppresshandlerscope?view=dotnet-plat-ext-8.0

也不起作用,因为它无法从根访问范围服务。

我发现的第三个解决方案是推荐 IHttpContextAccessor,但是这里:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-6.0#ihttpcontextaccessorhttpcontext-in-razor -components-blazor,我有点担心。

我愿意:

防止在 WebAssembly 应用程序中创建第二个作用域。

或者

从 DelegatingHandler 访问页面正在使用的相同范围。

(或者如何避免为每个注入服务创建多个实例的任何其他建议)

编辑:为什么这是一个问题? 具体来说,我正在使用组件库。该库注入范围服务。其中一项范围服务有一个项目列表。页面上的组件使用服务中的此列表。

显然修改此列表的副本对组件没有任何好处。

该服务获得两个实例,因为它已确定作用域,并且 HttpClientFactory 正在创建另一个作用域。

抑制范围创建选项,使构建器跳过“CreateScope()”,但构建器本身是单例的,因此您不能再使用范围。

我想强制 HttpClient 使用与 WebAssembly 相同的范围,但似乎没有任何解决方案。

dependency-injection blazor-webassembly httpclientfactory
1个回答
0
投票

最好的解决方案是重新考虑你的设计,但如果不可能,你可以尝试像

ScopeHolder
注入 .net 的
IServiceScopeFactory
:

public class CustomScopeHolder
{
    private readonly IServiceScopeFactory _scopeFactory;
    private IServiceScope _scope;

    public CustomScopeHolder(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public void CreateScope()
    {
        _scope = _scopeFactory.CreateScope();
    }

    public T GetService<T>()
    {    
        return _scope.ServiceProvider.GetRequiredService<T>();
    }

当然将其注册为单例:

services.AddSingleton<CustomScopeHolder>();

您可以在代码页+自定义消息的生命周期中使用它(也许通过中间件?):

var scopeHolder = context.RequestServices.GetRequiredService<CustomScopeHolder>();
scopeHolder.CreateScope();

然后你可以轻松地将它注入(通过构造函数或其他方式):

1. code page
2. custom massage

并像这样使用它:

var scopedService = _scopeHolder.GetService<ScopedService>();
© www.soinside.com 2019 - 2024. All rights reserved.