与控制器的构造函数相比,Blazor 页面上的依赖注入

Dependency Injection on a Blazor page compared to a controller's constructor

我正在开发一个新应用程序,我选择使用 Blazor 服务器端。我有现有的后端设置,正在尝试仅替换 UI 项目。我有一个用于所有服务的注册表,这个注册表用于 API 和 Blazor UI 项目:

public class DependencyContainer
{

    public static void RegisterServices(IServiceCollection services)
    {
        #region Domain InMemoryBus MediatR

        services.AddScoped<IMediatorHandler, InMemoryBus>();

        #endregion

        #region Domain Handlers

        services.AddScoped<IRequestHandler<RadarCreateCommand, bool>, RadarProjectCommandHandler>();

        #endregion

        #region Application Layer

        services.AddScoped<IRadarProjectService, RadarProjectService>();
        //services.AddScoped<IContactService, ContactService>();
        //services.AddScoped<ICategoryService, CategoryService>();
        //services.AddScoped<ISubCategoryService, SubCategoryService>();

        #endregion

        #region Infrastructure/Data Layer

        services.AddScoped<IPlaygroundBiRepository, PlaygroundBiRepository>();
        //services.AddScoped<IContactRepository, ContactRepository>();
        //services.AddScoped<ICategoryRepository, CategoryRepository>();
        //services.AddScoped<ISubCategoryRepository, SubCategoryRepository>();

        services.AddScoped<DesignTrackerContext>();
        services.AddScoped<PlaygroundBiContext>();

        #endregion

    }

}

在我的 Blazor 项目中,我有对注册表项目的引用,并在 'Startup.cs' 中将此方法调用为:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        ...
        services.AddMediatR(typeof(Startup));
        services.RegisterAutoMapper();

        RegisterServices(services);
    }

现在,我想在我的页面上显示一个项目列表。有一项服务将公开所有项目的非实体 POCO。页面设置如下:

@page "/projects"
@using DesignTracker.Application.Interfaces
@using DesignTracker.Application.ViewModels

<div class="container-fluid">
    <div class="row my-4">
        <div class="col-12">
            <TelerikGrid Data="@allProjects" Height="550px" FilterMode="@GridFilterMode.FilterMenu"
                         Sortable="true" Pageable="true" PageSize="20" Groupable="true"
                         EditMode="@GridEditMode.Inline">
                <GridColumns>
                    <GridColumn Field="Id" Title="Id" Width="100px" Editable="false" Groupable="false" />
                    <GridColumn Field="Date">
                        <Template>
                            @((context as RadarProjectViewModel).LastUpdateTime?.ToString("dddd, dd MMM yyyy"))
                        </Template>
                    </GridColumn>
                    <GridColumn Field="Name" />
                    <GridColumn Field="Department" />
                    <GridColumn Field="Summary" />
                    <GridCommandColumn>
                        <GridCommandButton Command="Save" Icon="@IconName.Save" ShowInEdit="true">Update</GridCommandButton>
                        <GridCommandButton Command="Edit" Icon="@IconName.Edit" Primary="true">Edit</GridCommandButton>
                        <GridCommandButton Command="Delete" Icon="@IconName.Delete">Delete</GridCommandButton>
                        <GridCommandButton Command="Cancel" Icon="@IconName.Cancel" ShowInEdit="true">Cancel</GridCommandButton>
                    </GridCommandColumn>
                </GridColumns>
                <GridToolBar>
                    <GridCommandButton Command="Add" Icon="@IconName.Plus" Primary="true">Add Project</GridCommandButton>
                </GridToolBar>
            </TelerikGrid>
        </div>
    </div>
</div>

@code {
    private readonly IRadarProjectService _service;
    private IEnumerable<RadarProjectViewModel> allProjects;
}

如果我按照 Blazor 模板附带的 WeatherService 示例进行操作,我看不到 IoC 正在运行,因为在 OnInitializedAsync() 中调用了一个实际初始化预测的方法:

List<WeatherForecast> forecasts { get; set; }

protected override async Task OnInitializedAsync()
{
    await GetForecasts();
}

async Task GetForecasts()
{
    forecasts = await ForecastService.GetForecastListAsync(DateTime.Now);
}

根据我的 MVC 和 Asp.Net 核心经验,我需要做的就是为我需要的服务创建支持接口并创建一个加载的构造函数,然后 DI 引擎将在运行时注入初始化的对象。

这在 Blazor 的 code{ ... } 中怎么可能?

要直接在 blazor 页面上应用依赖注入,请使用 @inject 指令。

例子

.razor 页数:

@page "/"
@using YourServiceNamespace

@inject IYourService yourService // Here injecting dependency

<div>/*some html here*/</div>

@code 
{
    public string[] ArrayOfStrings => yourService.GetArrayOfStrings(); 
}

Startup.cs 文件:

services.AddScoped<IYourService, YourService>();

Blazor 会自动从应用程序环境接收您的服务并将其直接注入页面,以便您可以像从普通 csharp 代码一样使用它。