在普通的 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 或已注册的接口,则
- 那些依赖项本身会实例化(如果尚未完成的话)
- 实例被传递给原始 dep 上的构造函数
此链必须由 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( ..... );
}
}
例如,模板生成的代码有
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 或已注册的接口,则
- 那些依赖项本身会实例化(如果尚未完成的话)
- 实例被传递给原始 dep 上的构造函数
此链必须由 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( ..... );
}
}