【问题标题】:Initialize Service in Blazor Webassembly在 Blazor Webassembly 中初始化服务
【发布时间】:2021-10-26 16:08:58
【问题描述】:

我有一个服务 A 在各个组件之间共享。该服务需要在启动时使用来自 WebApi 的值进行初始化。

我怎样才能做到这一点?我尝试了两件事。

_1.

在 program.cs/main 方法中我做

builder.Services.AddScoped

与 A 和其他服务 B 和 C。

然后我调用一个方法

async LoadSetupData(wasmBuilder)

通过

获得服务A、B、C
wasmBuilder.GetRequiredService<T(A)>...

然后

A.MySetupValues = await B.GetSetupValues().

通过 WebApi 检索值。

到目前为止有效。但是当我通过 [Inject] A a 在组件中使用 A 时,我得到的服务对象不是我在 LoadSetupData 中检索到的那个(服务有一个 Guid 属性,它们是不同的)。

_2.

我尝试通过向 AddScoped 提供工厂方法来添加 A。这不起作用,因为从 WebApi 获取值本质上是异步的。并且不能从 program.cs/main 使用异步调用(“无法在此运行时等待监视器”)。

非常感谢您的阅读!非常感谢任何帮助!

【问题讨论】:

  • async LoadSetupData(wasmBuilder) 既不是调用也不是定义,只是无效的 C#。你在等吗?
  • 这是伪代码!是的,我确实在等待它。
  • 太伪了。这样你就会得到伪答案。阅读minimal reproducible example
  • 为什么需要预加载数据?当第一个组件需要它时获取它。你说“我有一个服务 A,它在各个组件之间共享。”然后你开始谈论服务 A、B、C。如果服务 A 的范围是但您获得不同的 guid,那么您很可能会重新启动 SPA。组件 A、B、C.... 都将在同一个 SPA “会话”中获得同一个 Scoped Service A 实例。与上面关于“伪代码”的想法相同。
  • 如果你认为你必须讨论如何使用伪代码,那么你就不懂伪代码。琐碎地讨论它的细节直接违背了它的目的。我现在投票决定停止这种反叛,因为它对任何人都没有好处。

标签: asynchronous .net-core blazor asp.net-core-webapi webassembly


【解决方案1】:

您可以在 Program.cs 中加载数据,然后指出如何解决依赖注入。

var datas = await (new TheProvidingDataService()).LoadDataAsync();
builder.Services.AddSingleton(s => new NeedYourDataService(data));

【讨论】:

  • 虽然我认为我的回答是正确的,但在考虑之前你应该看看enterprisecraftsmanship.com/posts/…。在应用程序边缘加载数据是有代价的(也是有回报的)。
  • 在应用程序边缘加载数据是有代价的(和奖励)。我认为没有价格,可以有更高的启动时间,但从“全球”性能的角度来看,我认为这是一个助推器。如果服务器有足够的内存是一个很好的做法来加载所有可能在内存中不经常更改的数据。你更喜欢“更轻”的方法吗?更“DDD”/修身时尚?
  • 如果数据量有限,(参考数据)很适合。
【解决方案2】:

感谢您的所有回答!我能够通过在 OnInitializedAsync 中的 App 组件中进行初始化来解决问题。

[Inject] IServiceProvider sp { get; set; }

protected override async Task OnInitializedAsync() {

  ISvcB svcb = sp.GetRequiredService<ISvcB>();
  ISvcA svca = sp.GetRequiredService<ISvcA>();

  svca.SetupData = await svcb.GetSetupData();
}

【讨论】:

    【解决方案3】:

    尝试重新定义您的设计。

    我更喜欢在构造函数中对服务进行所有初始化。
    你需要一些其他的服务(B&C),所以需要在服务A的构造函数中使用DI。

    解决方案“A”

    我认为以下设计应该适合您的情况:

    builder.Services.AddScoped<IServiceA,ServiceA>();
    
    var hostInstance = builder.services.Build();
    var theServiceA = hostInstance.GetRequiredService<IServiceA>();
    
    ...
    
    hostInstance.RunAsync()
    

    解决方案“B”

    试试这个:

    builder.Services.AddScoped(sp => sp.GetRequiredService<IServiceA>().LoadSetupData());
    

    请注意,在 Blazor WASM 中 ScopedSingleton 生命周期是相同的。不在服务器中。

    【讨论】:

    • 我确实认为您的解决方案会起作用。不过,我尽量让我的构造函数保持快速和简单。从 WebApi 加载数据与这个想法背道而驰。
    猜你喜欢
    • 2023-03-31
    • 2021-08-22
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    • 2021-03-27
    相关资源
    最近更新 更多