在 ASP.NET Core Blazor WebAssembly 中延迟加载程序集

通过等待应用程序集直到需要时才加载,提高 Blazor WebAssembly 应用启动性能,这种方式称为“延迟加载”。

本文的初始部分介绍了应用配置。 如需有效的演示,请参阅本文末尾的完整示例部分。

备注

由于 Blazor Server 应用程序集不会被下载到客户端,因此程序集的延迟加载对 Blazor Server 应用并没有好处。

项目文件配置

使用 BlazorWebAssemblyLazyLoad 项标记应用的项目文件 (.csproj) 中用于延迟加载的程序集。 使用带 .dll 扩展名的程序集名称。 Blazor 框架会阻止程序集在应用启动时加载。

<ItemGroup>
  <BlazorWebAssemblyLazyLoad Include="{ASSEMBLY NAME}.dll" />
</ItemGroup>

{ASSEMBLY NAME} 占位符是程序集的名称。 .dll 文件扩展名是必需的。

每个程序集都包含一个 BlazorWebAssemblyLazyLoad 项。 如果程序集具有依赖项,则每个依赖项都包含一个 BlazorWebAssemblyLazyLoad 条目。

Router 组件配置

Blazor 框架会自动为客户端 Blazor WebAssembly 应用†、LazyAssemblyLoader 中的延迟加载程序集注册单一服务。 LazyAssemblyLoader.LoadAssembliesAsync 方法:

  • 使用 JS 互操作通过网络调用提取程序集。
  • 在浏览器中将程序集加载到正在 WebAssembly 上执行的运行时。

†有关托管的 Blazor WebAssembly 解决方案的指南包含在托管的 Blazor WebAssembly 解决方案中的延迟加载程序集部分。

Blazor 的 Router 组件指定 Blazor 搜索可路由组件的程序集,并负责为用户导航的路由呈现组件。 Router 组件的 OnNavigateAsync 方法 与延迟加载结合使用,以便为用户请求的终结点加载正确的程序集。

逻辑在 OnNavigateAsync 内实现,以确定要使用 LazyAssemblyLoader 加载的程序集。 逻辑构建方式的选项包括:

  • OnNavigateAsync 方法内部的条件检查。
  • 一个将路由映射到程序集名称的查找表,可以注入到组件中,也可以在 @code 块内实现。

如下示例中:

  • 指定了 Microsoft.AspNetCore.Components.WebAssembly.Services 的命名空间。
  • 注入了 LazyAssemblyLoader 服务 (AssemblyLoader)。
  • {PATH} 占位符是程序集列表应加载到的路径。 该示例对加载一组程序集的单个路径使用条件检查。
  • {LIST OF ASSEMBLIES} 占位符是以逗号分隔的程序集文件名字符串列表,包括它们的 .dll 扩展名(例如 "Assembly1.dll", "Assembly2.dll")。

App.razor:

@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger

<Router AppAssembly="@typeof(Program).Assembly" 
    OnNavigateAsync="@OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
           {
               if (args.Path == "{PATH}")
               {
                   var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                       new[] { {LIST OF ASSEMBLIES} });
               }
           }
           catch (Exception ex)
           {
               Logger.LogError("Error: {Message}", ex.Message);
           }
    }
}

备注

前面的示例没有显示 Router 组件的 Razor 标记 (...) 的内容。 有关完整代码的演示,请参阅本文的完整示例部分。

包含可路由组件的程序集

当程序集列表包含可路由组件时,指定路径的程序集列表将传递到 Router 组件的 AdditionalAssemblies 集合。

如下示例中:

  • lazyLoadedAssemblies 中的 List<Assembly> 将程序集列表传递给 AdditionalAssemblies。 框架会搜索程序集中的路由,并在发现新路由时更新路由集合。 要访问 Assembly 类型,请将 System.Reflection 的命名空间包含在 App.razor 文件的顶部。
  • {PATH} 占位符是程序集列表应加载到的路径。 该示例对加载一组程序集的单个路径使用条件检查。
  • {LIST OF ASSEMBLIES} 占位符是以逗号分隔的程序集文件名字符串列表,包括它们的 .dll 扩展名(例如 "Assembly1.dll", "Assembly2.dll")。

App.razor:

@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger

<Router AppAssembly="@typeof(Program).Assembly" 
    AdditionalAssemblies="@lazyLoadedAssemblies" 
    OnNavigateAsync="@OnNavigateAsync">
    ...
</Router>

@code {
    private List<Assembly> lazyLoadedAssemblies = new();

    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
           {
               if (args.Path == "{PATH}")
               {
                   var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                       new[] { {LIST OF ASSEMBLIES} });
                   lazyLoadedAssemblies.AddRange(assemblies);
               }
           }
           catch (Exception ex)
           {
               Logger.LogError("Error: {Message}", ex.Message);
           }
    }
}

备注

前面的示例没有显示 Router 组件的 Razor 标记 (...) 的内容。 有关完整代码的演示,请参阅本文的完整示例部分。

有关详细信息,请参阅 ASP.NET Core Blazor 路由

用户与 <Navigating> 内容的交互

加载程序集可能需要几秒钟的时间,Router 组件可以通过路由器的 Navigating 属性向用户指示正在发生页面转换。

有关详细信息,请参阅 ASP.NET Core Blazor 路由

处理 OnNavigateAsync 中的取消

传递到 OnNavigateAsync 回调的 NavigationContext 对象包含的 CancellationToken 在发生新导航事件时进行设置。 设置取消标记时,OnNavigateAsync 回调必须引发,以避免在过时的导航中继续运行 OnNavigateAsync 回调。

有关详细信息,请参阅 ASP.NET Core Blazor 路由

OnNavigateAsync 事件和重命名的程序集文件

资源加载程序依赖于在 blazor.boot.json 文件中定义的程序集名称。 如果程序集已重命名,则 OnNavigateAsync 回叫中使用的程序集名称和 blazor.boot.json 文件中的程序集名称将不同步。

若要更正此问题,请执行以下操作:

  • 确定要使用的程序集名称时,检查应用是否在 Production 环境中运行。
  • 将重命名的程序集名称存储在单独的文件中并从该文件中读取,以确定要与 LazyAssemblyLoader 服务和 OnNavigateAsync 回叫一起使用的程序集名称。

托管的 Blazor WebAssembly 解决方案中的延迟加载程序集

框架的延迟加载实现支持在托管的 Blazor WebAssembly 解决方案中使用预呈现进行延迟加载。 在预呈现期间,所有的程序集(包括那些被标记为延迟加载的程序集)都被假定为已加载。 在 Server 项目中手动注册 LazyAssemblyLoader 服务。

Server 项目的 Program.cs 文件顶部,添加 Microsoft.AspNetCore.Components.WebAssembly.Services 的命名空间:

using Microsoft.AspNetCore.Components.WebAssembly.Services;

Server 项目的 Program.cs 中,注册服务:

builder.Services.AddScoped<LazyAssemblyLoader>();

完整示例

本部分中的演示:

  • 创建机器人控制程序集 (GrantImaharaRobotControls.dll) 作为包含 Robot 组件的 Razor 类库 (RCL)Robot.razor,路由模板为 /robot)。
  • 当用户请求 /robot URL 时,延迟加载 RCL 的程序集以呈现其 Robot 组件。
  1. 创建新的 ASP.NET Core 类库项目:

    • Visual Studio:“创建解决方案” > “创建新项目” > “Razor 类库” 。 将项目命名为 GrantImaharaRobotControls
    • Visual Studio Code/.NET CLI:从命令提示符执行 dotnet new razorclasslib -o GrantImaharaRobotControls-o|--output 选项为解决方案创建文件夹并将项目命名为 GrantImaharaRobotControls
  2. 本部分后面介绍的示例组件使用 Blazor 表单。 为 Microsoft.AspNetCore.Components.Forms 添加对 RCL 项目的包引用:

    <PackageReference Include="Microsoft.AspNetCore.Components.Forms" Version="{VERSION}" />
    

    {VERSION} 占位符是包的版本。

  3. 使用 ThumbUp 方法在 RCL 中创建一个 HandGesture 类,该类可通过假设方式让机器人竖起大拇指。 该方法接受轴的参数 LeftRight,作为 enum。 该方法在成功时返回 true

    HandGesture.cs:

    using Microsoft.Extensions.Logging;
    
    namespace GrantImaharaRobotControls
    {
        public static class HandGesture
        {
            public static bool ThumbUp(Axis axis, ILogger logger)
            {
                logger.LogInformation("Thumb up gesture. Axis: {Axis}", axis);
    
                // Code to make robot perform gesture
    
                return true;
            }
        }
    
        public enum Axis { Left, Right }
    }
    
  4. 将以下组件添加到 RCL 项目的根目录。 通过该组件,用户可以提交竖起左手大拇指或右手大拇指的手势请求。

    Robot.razor:

    @page "/robot"
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.Extensions.Logging
    @inject ILogger<Robot> Logger
    
    <h1>Robot</h1>
    
    <EditForm Model="@robotModel" OnValidSubmit="@HandleValidSubmit">
        <InputRadioGroup @bind-Value="robotModel.AxisSelection">
            @foreach (var entry in (Axis[])Enum
                .GetValues(typeof(Axis)))
            {
                <InputRadio Value="@entry" />
                <text>&nbsp;</text>@entry<br>
            }
        </InputRadioGroup>
    
        <button type="submit">Submit</button>
    </EditForm>
    
    <p>
        @message
    </p>
    
    @code {
        private RobotModel robotModel = new() { AxisSelection = Axis.Left };
        private string message;
    
        private void HandleValidSubmit()
        {
            Logger.LogInformation("HandleValidSubmit called");
    
            var result = HandGesture.ThumbUp(robotModel.AxisSelection, Logger);
    
            message = $"ThumbUp returned {result} at {DateTime.Now}.";
        }
    
        public class RobotModel
        {
            public Axis AxisSelection { get; set; }
        }
    }
    

创建一个 Blazor WebAssembly 应用来演示 RCL 程序集的延迟加载:

  1. 使用 .NET CLI 在 Visual Studio、Visual Studio Code 中或通过命令提示符创建 Blazor WebAssembly 应用。 将项目命名为 LazyLoadTest

  2. GrantImaharaRobotControls RCL 创建项目引用:

    • Visual Studio:将 GrantImaharaRobotControls RCL 项目添加到解决方案(“添加” > “现有项目” )。 选择“添加” > “项目引用”,为 GrantImaharaRobotControls RCL 添加项目引用 。
    • Visual Studio Code/.NET CLI:在命令行界面中从项目文件夹执行 dotnet add reference {PATH}。 占位符 {PATH} 是 RCL 项目的路径。

构建并运行应用。 对于加载 Index 组件的默认页面 (Pages/Index.razor),开发人员工具的“网络”选项卡指示已加载 RCL 的程序集 GrantImaharaRobotControls.dllIndex 组件不使用程序集,因此加载程序集的效率不高。

在浏览器中加载的索引组件,其中包含开发人员工具的“网络”选项卡,指示已加载 GrantImaharaRobotControls.dll 程序集。

将应用配置为延迟加载 GrantImaharaRobotControls.dll 程序集:

  1. 在 Blazor WebAssembly 应用的项目文件 (.csproj) 中指定用于延迟加载的 RCL 程序集:

    <ItemGroup>
      <BlazorWebAssemblyLazyLoad Include="GrantImaharaRobotControls.dll" />
    </ItemGroup>
    
  2. 以下 Router 组件演示了在用户导航到 /robot 时如何加载 GrantImaharaRobotControls.dll 程序集。 将应用的默认 App 组件替换为以下 App 组件。

    在页面转换期间,系统会向用户显示一条具有 <Navigating> 元素的有样式消息。 有关详细信息,请参阅用户与 <Navigating> 内容互动部分。

    程序集会分配给 AdditionalAssemblies,这会导致路由器在程序集中搜索可路由组件,并在其中找到 Robot 组件。 Robot 组件的路由将添加到应用的路由集合中。 有关详细信息,请参阅 ASP.NET Core Blazor 路由 一文和本文的包含可路由组件的程序集部分。

    App.razor:

    @using System.Reflection
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.WebAssembly.Services
    @using Microsoft.Extensions.Logging
    @inject LazyAssemblyLoader AssemblyLoader
    @inject ILogger<App> Logger
    
    <Router AppAssembly="@typeof(Program).Assembly"
            AdditionalAssemblies="@lazyLoadedAssemblies" 
            OnNavigateAsync="@OnNavigateAsync">
        <Navigating>
            <div style="padding:20px;background-color:blue;color:white">
                <p>Loading the requested page&hellip;</p>
            </div>
        </Navigating>
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
    
    @code {
        private List<Assembly> lazyLoadedAssemblies = new();
    
        private async Task OnNavigateAsync(NavigationContext args)
        {
            try
            {
                if (args.Path == "robot")
                {
                    var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                        new[] { "GrantImaharaRobotControls.dll" });
                    lazyLoadedAssemblies.AddRange(assemblies);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError("Error: {Message}", ex.Message);
            }
        }
    }
    

再次生成并运行应用。 对于加载 Index 组件 (Pages/Index.razor) 的默认页面,开发人员工具的“网络”选项卡指示 RCL 的程序集 (GrantImaharaRobotControls.dll) 未加载 Index 组件:

在浏览器中加载的索引组件,其中包含开发人员工具的“网络”选项卡,指示未加载 GrantImaharaRobotControls.dll 程序集。

如果在 https://localhost:5001/robot 处请求了来自 RCL 的 Robot 组件,则已加载 GrantImaharaRobotControls.dll 程序集并呈现了 Robot 组件:

在浏览器中加载的机器人组件,其中包含开发人员工具的“网络”选项卡,指示已加载 GrantImaharaRobotControls.dll 程序集。

疑难解答

  • 如果出现意外的呈现(例如呈现上一次导航中的组件),请确认在设置取消标记时是否引发代码。
  • 如果配置为延迟加载的程序集在应用启动时意外加载,请检查该程序集是否在项目文件中标记为延迟加载。

备注

从延迟加载的程序集中加载类型存在一个已知问题。 有关详细信息,请参阅在组件中使用 @ref 属性时 Blazor WebAssembly 延迟加载程序集不起作用 (dotnet/aspnetcore #29342)

其他资源

通过等待应用程序集直到需要时才加载,提高 Blazor WebAssembly 应用启动性能,这种方式称为“延迟加载”。

本文的初始部分介绍了应用配置。 如需有效的演示,请参阅本文末尾的完整示例部分。

备注

由于 Blazor Server 应用程序集不会被下载到客户端,因此程序集的延迟加载对 Blazor Server 应用并没有好处。

项目文件配置

使用 BlazorWebAssemblyLazyLoad 项标记应用的项目文件 (.csproj) 中用于延迟加载的程序集。 使用带 .dll 扩展名的程序集名称。 Blazor 框架会阻止程序集在应用启动时加载。

<ItemGroup>
  <BlazorWebAssemblyLazyLoad Include="{ASSEMBLY NAME}.dll" />
</ItemGroup>

{ASSEMBLY NAME} 占位符是程序集的名称。 .dll 文件扩展名是必需的。

每个程序集都包含一个 BlazorWebAssemblyLazyLoad 项。 如果程序集具有依赖项,则每个依赖项都包含一个 BlazorWebAssemblyLazyLoad 条目。

Router 组件配置

Blazor 框架会自动为客户端 Blazor WebAssembly 应用†、LazyAssemblyLoader 中的延迟加载程序集注册单一服务。 LazyAssemblyLoader.LoadAssembliesAsync 方法:

  • 使用 JS 互操作通过网络调用提取程序集。
  • 在浏览器中将程序集加载到正在 WebAssembly 上执行的运行时。

†有关托管的 Blazor WebAssembly 解决方案的指南包含在托管的 Blazor WebAssembly 解决方案中的延迟加载程序集部分。

Blazor 的 Router 组件指定 Blazor 搜索可路由组件的程序集,并负责为用户导航的路由呈现组件。 Router 组件的 OnNavigateAsync 方法 与延迟加载结合使用,以便为用户请求的终结点加载正确的程序集。

逻辑在 OnNavigateAsync 内实现,以确定要使用 LazyAssemblyLoader 加载的程序集。 逻辑构建方式的选项包括:

  • OnNavigateAsync 方法内部的条件检查。
  • 一个将路由映射到程序集名称的查找表,可以注入到组件中,也可以在 @code 块内实现。

如下示例中:

  • 指定了 Microsoft.AspNetCore.Components.WebAssembly.Services 的命名空间。
  • 注入了 LazyAssemblyLoader 服务 (AssemblyLoader)。
  • {PATH} 占位符是程序集列表应加载到的路径。 该示例对加载一组程序集的单个路径使用条件检查。
  • {LIST OF ASSEMBLIES} 占位符是以逗号分隔的程序集文件名字符串列表,包括它们的 .dll 扩展名(例如 "Assembly1.dll", "Assembly2.dll")。

App.razor:

@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger

<Router AppAssembly="@typeof(Program).Assembly" 
    OnNavigateAsync="@OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
           {
               if (args.Path == "{PATH}")
               {
                   var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                       new[] { {LIST OF ASSEMBLIES} });
               }
           }
           catch (Exception ex)
           {
               Logger.LogError("Error: {Message}", ex.Message);
           }
    }
}

备注

前面的示例没有显示 Router 组件的 Razor 标记 (...) 的内容。 有关完整代码的演示,请参阅本文的完整示例部分。

备注

随着 ASP.NET Core 5.0.1 的发布及任何附加 5.x 版本的推出,Router 组件包含 PreferExactMatches 参数(设置为 @true)。 有关详细信息,请参阅 从 ASP.NET Core 3.1 迁移到 5.0

包含可路由组件的程序集

当程序集列表包含可路由组件时,指定路径的程序集列表将传递到 Router 组件的 AdditionalAssemblies 集合。

如下示例中:

  • lazyLoadedAssemblies 中的 List<Assembly> 将程序集列表传递给 AdditionalAssemblies。 框架会搜索程序集中的路由,并在发现新路由时更新路由集合。 要访问 Assembly 类型,请将 System.Reflection 的命名空间包含在 App.razor 文件的顶部。
  • {PATH} 占位符是程序集列表应加载到的路径。 该示例对加载一组程序集的单个路径使用条件检查。
  • {LIST OF ASSEMBLIES} 占位符是以逗号分隔的程序集文件名字符串列表,包括它们的 .dll 扩展名(例如 "Assembly1.dll", "Assembly2.dll")。

App.razor:

@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger

<Router AppAssembly="@typeof(Program).Assembly" 
    AdditionalAssemblies="@lazyLoadedAssemblies" 
    OnNavigateAsync="@OnNavigateAsync">
    ...
</Router>

@code {
    private List<Assembly> lazyLoadedAssemblies = new();

    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
           {
               if (args.Path == "{PATH}")
               {
                   var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                       new[] { {LIST OF ASSEMBLIES} });
                   lazyLoadedAssemblies.AddRange(assemblies);
               }
           }
           catch (Exception ex)
           {
               Logger.LogError("Error: {Message}", ex.Message);
           }
    }
}

备注

前面的示例没有显示 Router 组件的 Razor 标记 (...) 的内容。 有关完整代码的演示,请参阅本文的完整示例部分。

备注

随着 ASP.NET Core 5.0.1 的发布及任何附加 5.x 版本的推出,Router 组件包含 PreferExactMatches 参数(设置为 @true)。 有关详细信息,请参阅 从 ASP.NET Core 3.1 迁移到 5.0

有关详细信息,请参阅 ASP.NET Core Blazor 路由

用户与 <Navigating> 内容的交互

加载程序集可能需要几秒钟的时间,Router 组件可以通过路由器的 Navigating 属性向用户指示正在发生页面转换。

有关详细信息,请参阅 ASP.NET Core Blazor 路由

处理 OnNavigateAsync 中的取消

传递到 OnNavigateAsync 回调的 NavigationContext 对象包含的 CancellationToken 在发生新导航事件时进行设置。 设置取消标记时,OnNavigateAsync 回调必须引发,以避免在过时的导航中继续运行 OnNavigateAsync 回调。

有关详细信息,请参阅 ASP.NET Core Blazor 路由

OnNavigateAsync 事件和重命名的程序集文件

资源加载程序依赖于在 blazor.boot.json 文件中定义的程序集名称。 如果程序集已重命名,则 OnNavigateAsync 回叫中使用的程序集名称和 blazor.boot.json 文件中的程序集名称将不同步。

若要更正此问题,请执行以下操作:

  • 确定要使用的程序集名称时,检查应用是否在 Production 环境中运行。
  • 将重命名的程序集名称存储在单独的文件中并从该文件中读取,以确定要与 LazyAssemblyLoader 服务和 OnNavigateAsync 回叫一起使用的程序集名称。

托管的 Blazor WebAssembly 解决方案中的延迟加载程序集

框架的延迟加载实现支持在托管的 Blazor WebAssembly 解决方案中使用预呈现进行延迟加载。 在预呈现期间,所有的程序集(包括那些被标记为延迟加载的程序集)都被假定为已加载。 在 Server 项目中手动注册 LazyAssemblyLoader 服务。

Server 项目的 Startup.cs 文件顶部,添加 Microsoft.AspNetCore.Components.WebAssembly.Services 的命名空间:

using Microsoft.AspNetCore.Components.WebAssembly.Services;

Server 项目的 Startup.ConfigureServices 方法 (Startup.cs) 中,注册服务:

services.AddScoped<LazyAssemblyLoader>();

完整示例

本部分中的演示:

  • 创建机器人控制程序集 (GrantImaharaRobotControls.dll) 作为包含 Robot 组件的 Razor 类库 (RCL)Robot.razor,路由模板为 /robot)。
  • 当用户请求 /robot URL 时,延迟加载 RCL 的程序集以呈现其 Robot 组件。
  1. 创建新的 ASP.NET Core 类库项目:

    • Visual Studio:“创建解决方案” > “创建新项目” > “Razor 类库” 。 将项目命名为 GrantImaharaRobotControls
    • Visual Studio Code/.NET CLI:从命令提示符执行 dotnet new razorclasslib -o GrantImaharaRobotControls-o|--output 选项为解决方案创建文件夹并将项目命名为 GrantImaharaRobotControls
  2. 本部分后面介绍的示例组件使用 Blazor 表单。 为 Microsoft.AspNetCore.Components.Forms 添加对 RCL 项目的包引用:

    <PackageReference Include="Microsoft.AspNetCore.Components.Forms" Version="{VERSION}" />
    

    {VERSION} 占位符是包的版本。

  3. 使用 ThumbUp 方法在 RCL 中创建一个 HandGesture 类,该类可通过假设方式让机器人竖起大拇指。 该方法接受轴的参数 LeftRight,作为 enum。 该方法在成功时返回 true

    HandGesture.cs:

    using Microsoft.Extensions.Logging;
    
    namespace GrantImaharaRobotControls
    {
        public static class HandGesture
        {
            public static bool ThumbUp(Axis axis, ILogger logger)
            {
                logger.LogInformation("Thumb up gesture. Axis: {Axis}", axis);
    
                // Code to make robot perform gesture
    
                return true;
            }
        }
    
        public enum Axis { Left, Right }
    }
    
  4. 将以下组件添加到 RCL 项目的根目录。 通过该组件,用户可以提交竖起左手大拇指或右手大拇指的手势请求。

    Robot.razor:

    @page "/robot"
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.Extensions.Logging
    @inject ILogger<Robot> Logger
    
    <h1>Robot</h1>
    
    <EditForm Model="@robotModel" OnValidSubmit="@HandleValidSubmit">
        <InputRadioGroup @bind-Value="robotModel.AxisSelection">
            @foreach (var entry in (Axis[])Enum
                .GetValues(typeof(Axis)))
            {
                <InputRadio Value="@entry" />
                <text>&nbsp;</text>@entry<br>
            }
        </InputRadioGroup>
    
        <button type="submit">Submit</button>
    </EditForm>
    
    <p>
        @message
    </p>
    
    @code {
        private RobotModel robotModel = new() { AxisSelection = Axis.Left };
        private string message;
    
        private void HandleValidSubmit()
        {
            Logger.LogInformation("HandleValidSubmit called");
    
            var result = HandGesture.ThumbUp(robotModel.AxisSelection, Logger);
    
            message = $"ThumbUp returned {result} at {DateTime.Now}.";
        }
    
        public class RobotModel
        {
            public Axis AxisSelection { get; set; }
        }
    }
    

创建一个 Blazor WebAssembly 应用来演示 RCL 程序集的延迟加载:

  1. 使用 .NET CLI 在 Visual Studio、Visual Studio Code 中或通过命令提示符创建 Blazor WebAssembly 应用。 将项目命名为 LazyLoadTest

  2. GrantImaharaRobotControls RCL 创建项目引用:

    • Visual Studio:将 GrantImaharaRobotControls RCL 项目添加到解决方案(“添加” > “现有项目” )。 选择“添加” > “项目引用”,为 GrantImaharaRobotControls RCL 添加项目引用 。
    • Visual Studio Code/.NET CLI:在命令行界面中从项目文件夹执行 dotnet add reference {PATH}。 占位符 {PATH} 是 RCL 项目的路径。

构建并运行应用。 对于加载 Index 组件的默认页面 (Pages/Index.razor),开发人员工具的“网络”选项卡指示已加载 RCL 的程序集 GrantImaharaRobotControls.dllIndex 组件不使用程序集,因此加载程序集的效率不高。

在浏览器中加载的索引组件,其中包含开发人员工具的“网络”选项卡,指示已加载 GrantImaharaRobotControls.dll 程序集。

将应用配置为延迟加载 GrantImaharaRobotControls.dll 程序集:

  1. 在 Blazor WebAssembly 应用的项目文件 (.csproj) 中指定用于延迟加载的 RCL 程序集:

    <ItemGroup>
      <BlazorWebAssemblyLazyLoad Include="GrantImaharaRobotControls.dll" />
    </ItemGroup>
    
  2. 以下 Router 组件演示了在用户导航到 /robot 时如何加载 GrantImaharaRobotControls.dll 程序集。 将应用的默认 App 组件替换为以下 App 组件。

    在页面转换期间,系统会向用户显示一条具有 <Navigating> 元素的有样式消息。 有关详细信息,请参阅用户与 <Navigating> 内容互动部分。

    程序集会分配给 AdditionalAssemblies,这会导致路由器在程序集中搜索可路由组件,并在其中找到 Robot 组件。 Robot 组件的路由将添加到应用的路由集合中。 有关详细信息,请参阅 ASP.NET Core Blazor 路由 一文和本文的包含可路由组件的程序集部分。

    App.razor:

    @using System.Reflection
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.WebAssembly.Services
    @using Microsoft.Extensions.Logging
    @inject LazyAssemblyLoader AssemblyLoader
    @inject ILogger<App> Logger
    
    <Router AppAssembly="@typeof(Program).Assembly"
            AdditionalAssemblies="@lazyLoadedAssemblies" 
            OnNavigateAsync="@OnNavigateAsync">
        <Navigating>
            <div style="padding:20px;background-color:blue;color:white">
                <p>Loading the requested page&hellip;</p>
            </div>
        </Navigating>
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
    
    @code {
        private List<Assembly> lazyLoadedAssemblies = new();
    
        private async Task OnNavigateAsync(NavigationContext args)
        {
            try
            {
                if (args.Path == "robot")
                {
                    var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                        new[] { "GrantImaharaRobotControls.dll" });
                    lazyLoadedAssemblies.AddRange(assemblies);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError("Error: {Message}", ex.Message);
            }
        }
    }
    

    备注

    随着 ASP.NET Core 5.0.1 的发布及任何附加 5.x 版本的推出,Router 组件包含 PreferExactMatches 参数(设置为 @true)。 有关详细信息,请参阅 从 ASP.NET Core 3.1 迁移到 5.0

再次生成并运行应用。 对于加载 Index 组件 (Pages/Index.razor) 的默认页面,开发人员工具的“网络”选项卡指示 RCL 的程序集 (GrantImaharaRobotControls.dll) 未加载 Index 组件:

在浏览器中加载的索引组件,其中包含开发人员工具的“网络”选项卡,指示未加载 GrantImaharaRobotControls.dll 程序集。

如果在 https://localhost:5001/robot 处请求了来自 RCL 的 Robot 组件,则已加载 GrantImaharaRobotControls.dll 程序集并呈现了 Robot 组件:

在浏览器中加载的机器人组件,其中包含开发人员工具的“网络”选项卡,指示已加载 GrantImaharaRobotControls.dll 程序集。

疑难解答

  • 如果出现意外的呈现(例如呈现上一次导航中的组件),请确认在设置取消标记时是否引发代码。
  • 如果配置为延迟加载的程序集在应用启动时意外加载,请检查该程序集是否在项目文件中标记为延迟加载。

备注

从延迟加载的程序集中加载类型存在一个已知问题。 有关详细信息,请参阅在组件中使用 @ref 属性时 Blazor WebAssembly 延迟加载程序集不起作用 (dotnet/aspnetcore #29342)

其他资源