在 Blazor 和 ASP.NET Core 中使用依赖注入和Scoped 服务实现数据共享方法详解

依赖注入(Dependency Injection,简称 DI)是一种设计模式,用于将对象的依赖关系从对象内部解耦出来,由外部容器进行管理和提供。在 Blazor 和 ASP.NET Core 中,DI 是内置的核心功能,它通过服务生命周期(Transient、Scoped、Singleton)来管理依赖项。


依赖注入(Dependency Injection)详解

核心概念

  1. 服务(Service):

    • 服务是一个类,封装了某些功能,可以被应用程序的其他部分使用。
  2. 服务容器(Service Container):

    • DI 容器是一个管理服务实例的工具,负责创建和提供服务实例。
    • ASP.NET Core 和 Blazor 中,IServiceCollection 是服务容器的接口,配置服务时通过它进行注册。
  3. 依赖关系:

    • 一个类如果需要另一个类来完成其功能,这种关系称为依赖关系。

DI 的优点

  • 解耦: 提高代码的模块化和可维护性。
  • 测试性: 通过注入模拟对象(mock)可以轻松测试。
  • 生命周期管理: DI 容器负责服务的创建、销毁和共享。

服务的生命周期

在 Blazor 和 ASP.NET Core 中,DI 服务的生命周期有三种:

  1. Transient(瞬态):

    • 每次请求都会创建一个新的实例。

    • 适合轻量级、无状态的服务。

      builder.Services.AddTransient<IMyService, MyService>();

  2. Scoped(作用域):

    • 在 Blazor Server 中,每个用户会话(或 SignalR 连接)会创建一个实例,并在整个会话中共享。

    • 在 Blazor WebAssembly 中,每个浏览器实例创建一个实例。

    • 适合与特定会话相关的服务。

      builder.Services.AddScoped<IMyService, MyService>();

  3. Singleton(单例):

    • 应用程序的整个生命周期中只有一个实例。

    • 适合全局共享的服务。

      builder.Services.AddSingleton<IMyService, MyService>();


Scoped 服务详解

Scoped 服务的行为

  1. Blazor Server:

    • 每个用户连接(SignalR 会话)有一个独立的实例。
    • 同一个用户的多个标签页共享同一个实例。
  2. Blazor WebAssembly:

    • 每个浏览器实例都有独立的 Scoped 服务实例。
    • 每个标签页有独立的实例。

实现 Scoped 服务

创建 Scoped 服务
  1. 创建一个服务类:

    public class UserInfoService 
    { 
         public string UserName { get; set; } 
         public string Role { get; set; } 
    } 
    
  2. Program.cs 中注册服务:

    builder.Services.AddScoped<UserInfoService>(); 
    
使用 Scoped 服务

在页面或组件中注入服务:

@inject UserInfoService UserInfoService 
<p>当前用户: @UserInfoService.UserName</p> 

在组件的代码部分更新或读取服务状态:

<button @onclick="SetUserInfo">设置用户信息</button> 

@code 
{ 
    private void SetUserInfo() 
       { 
            UserInfoService.UserName = "John Doe"; 
            UserInfoService.Role = "Admin"; 
       } 
} 

Scoped 服务的作用与场景

  1. 用户会话管理:

    • 保存用户的基本信息(用户名、角色等)。
    • 保存会话中需要共享的临时数据。
  2. 中间状态存储:

    • 用于在多步操作中保存状态(如分步骤表单)。
  3. 与数据库或外部服务交互:

    • 每个用户操作的独立上下文(如数据库上下文 DbContext)。

Scoped 服务的注意事项

  1. 线程安全:

    • 在 Blazor Server 中,多个组件可能同时访问 Scoped 服务,确保使用线程安全的方式处理数据。
  2. 避免与 Singleton 服务共享数据:

    • 如果需要共享 Scoped 服务与 Singleton 服务的数据,需特别小心数据一致性问题。
  3. Blazor Server 中多标签页问题:

    • 同一个用户的多个标签页共享 Scoped 服务实例。如果需要为每个标签页提供独立的状态,可以结合 Circuit 或切换为 Transient 服务。

Scoped 服务与其他生命周期的对比

生命周期 实例数 适用场景
Transient 每次请求创建新实例 无状态或轻量级的短期操作服务
Scoped 每个用户会话或浏览器实例一个 用户会话、临时状态
Singleton 整个应用程序一个实例 全局共享服务(如配置或缓存服务)

总结

  • Scoped 服务非常适合在 Blazor 中管理与用户会话相关的数据和状态。
  • 在 Blazor Server 中需要注意多标签页共享的问题;在 Blazor WebAssembly 中无需担心。
  • 使用 Scoped 服务时,保持线程安全是关键,尤其在 Blazor Server 环境下。

根据实际需求选择合适的服务生命周期,以实现高效、可靠的应用设计。

相关推荐
星辰大海的精灵几秒前
SpringBoot 整合 Elastic-Job 实现任务分布式调度
java·spring boot·后端
谦谦橘子1 分钟前
手写React useEffect方法,理解useEffect原理
前端·javascript·react.js
玉面小君2 分钟前
C# 设计模式(行为型模式):访问者模式
设计模式·c#·访问者模式
Q_19284999069 分钟前
基于Spring Boot微信小程序电影管理系统
spring boot·后端·微信小程序
玉面小君22 分钟前
C# 设计模式(行为型模式):模板方法模式
设计模式·c#·模板方法模式
九州~空城28 分钟前
C++中map和set的封装
java·前端·c++
椒盐大肥猫34 分钟前
axios拦截器底层实现原理
前端·javascript
Libby博仙35 分钟前
什么是.net framework,什么是.net core,什么是.net5~8,版本对应关系
.netcore
夕水1 小时前
我的2024-人生须为有益事
前端·年终总结
念言-ny1 小时前
springboot远程链接Hadoop
hadoop·spring boot·后端