在普通的 c# 代码中访问 blazor (wasm) 注入的对象,而不是 razor 页面

Accessing blazor (wasm) injected objects in plain c# code as opposed to razor page

例如,模板生成的代码有

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

并且这里使用此服务

@page "/fetchdata"
@inject HttpClient Http
...
protected override async Task OnInitializedAsync()
{
    forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}

很好,但是我可以从普通的 c# 文件访问该服务吗?

我尝试手动输入@inject 生成的内容,但这似乎不起作用:-

[Inject]
HttpClient Http {get;set;};

编辑 - 综合各种评论和答案的答案

当依赖项被 DI 系统实例化时,如果其构造函数的参数为​​ classes 或已注册的接口,则

此链必须由 blazor 页面上某处的 @inject / [inject] 启动。

以我为例。如果我在 class 中有一些代码称为 DbIo,则需要 HttpClient。必须做

public class DbIo{
     HttpClient _http;
     // constructor effectively announcing the dependencies
     public DbIo(HttpClient _http){
         _http = http;
     }
}

添加

 builder.Services.AddScoped<DbIo>();

到program.cs,并添加(这是不明显的一点)

 @inject DbIo DbService

到 blazor 页面(比如 App.razor)。这会强制实例化 DbIo 实例,并因此通过其构造函数传递其他服务。

我在使用 Blazor Wasm 时遇到了类似的问题。

我使用加载页面并在 OnInitialized() 覆盖方法中手动注入我需要的内容。

由于某些原因,这些标志在 .cs 文件中不起作用,但它们在 .razor 中总是起作用。所以,我从 .razor 页面注入它们,比如“Setup(neededObject)”。

这就是依赖注入的本质。如果根对象由 DI 容器提供,那么它可以解析所有构造函数参数,假设它们也在 DI 容器中注册。

Razor Components/Pages 由 Blazor 框架提供,Blazor 框架负责解析注入的属性(假设它们已在 DI 容器中注册)。

builder.Services.AddScoped(sp => 
    new HttpClient 
    { 
        BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 
    });

...将 HttpClient 添加到 DI 容器。

当您的 FetchData 页面由 Blazor 框架提供时,它将提供标有指令 @inject 的服务。在这种情况下...... HttpClient.

使用自定义服务...

如果您想在您的页面和 HttpClient 之间使用服务,以便该页面不直接与 HttpClient 一起工作,那么您需要在 DI 容器中注册该服务。

builder.Services.AddScoped<MyCustomService>();

然后,在你的 razor 页面中,你可以注入 MyCustomService:

@inject MyCustomService CustomService

既然 MyCustomService 是由 DI 容器提供的,它就可以在它的构造函数参数中请求 HttpClient(因为 HttpClient 也在 DI 容器中注册):

public class MyCustomService
{
    readonly HttpClient _httpClient;
    
    public MyCustomService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
    
    public async Task ApiMethod()
    {
        await _httpClient.PostAsync( ..... );
    }
}