You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server(.NET6):如何初始化需注入服务的基类属性?

解决方案

1. 基类自动加载权限(推荐)

利用Blazor组件生命周期的特性,基类的OnInitializedAsync会被自动调用,无需子类额外处理(仅需注意子类重写时必须调用基类方法)。

基类代码

public abstract class AuthComponentBase : ComponentBase
{
    [Inject]
    protected ProtectedSessionStorage ProtectedSessionStorage { get; set; } = null!;

    // 直接供子类使用的权限属性
    public bool IsApprover { get; protected set; }
    public bool IsOwner { get; protected set; }
    public bool IsViewer { get; protected set; } // 对应第三个角色

    protected override async Task OnInitializedAsync()
    {
        // 从ProtectedSessionStorage读取预存的角色状态
        var approverResult = await ProtectedSessionStorage.GetAsync<bool>("IsApprover");
        IsApprover = approverResult.Success ? approverResult.Value : false;

        var ownerResult = await ProtectedSessionStorage.GetAsync<bool>("IsOwner");
        IsOwner = ownerResult.Success ? ownerResult.Value : false;

        var viewerResult = await ProtectedSessionStorage.GetAsync<bool>("IsViewer");
        IsViewer = viewerResult.Success ? viewerResult.Value : false;

        await base.OnInitializedAsync();
    }
}

子类使用示例

@page "/"
@inherits AuthComponentBase

<h1>首页</h1>

@if (IsApprover)
{
    <button class="btn btn-primary">审批操作</button>
}

@if (IsOwner)
{
    <button class="btn btn-danger">管理配置</button>
}

注意:如果子类需要重写OnInitializedAsync,必须添加await base.OnInitializedAsync();,否则基类的权限加载逻辑不会执行。

2. 懒加载优化(按需读取)

如果部分组件不需要加载所有权限属性,可以用懒加载方式,仅在第一次访问属性时读取存储:

基类代码

public abstract class AuthComponentBase : ComponentBase
{
    [Inject]
    protected ProtectedSessionStorage ProtectedSessionStorage { get; set; } = null!;

    private bool? _isApprover;
    public async ValueTask<bool> GetIsApproverAsync()
    {
        if (_isApprover.HasValue)
            return _isApprover.Value;

        var result = await ProtectedSessionStorage.GetAsync<bool>("IsApprover");
        _isApprover = result.Success ? result.Value : false;
        return _isApprover.Value;
    }

    // 同理实现GetIsOwnerAsync、GetIsViewerAsync
}

子类使用示例

@if (await GetIsApproverAsync())
{
    <button>审批操作</button>
}

3. 全局状态容器(更高效)

如果想避免每个组件重复读取SessionStorage,可创建全局权限服务,登录时一次性加载所有权限:

权限状态服务

public class PermissionStateService
{
    private readonly ProtectedSessionStorage _sessionStorage;
    public bool IsApprover { get; private set; }
    public bool IsOwner { get; private set; }

    public PermissionStateService(ProtectedSessionStorage sessionStorage)
    {
        _sessionStorage = sessionStorage;
    }

    // 登录时调用此方法加载权限
    public async Task LoadPermissionsAsync()
    {
        var approverResult = await _sessionStorage.GetAsync<bool>("IsApprover");
        IsApprover = approverResult.Success ? approverResult.Value : false;

        var ownerResult = await _sessionStorage.GetAsync<bool>("IsOwner");
        IsOwner = ownerResult.Success ? ownerResult.Value : false;
    }
}

注册服务(Program.cs)

builder.Services.AddScoped<PermissionStateService>();

基类改造

public abstract class AuthComponentBase : ComponentBase
{
    [Inject]
    protected PermissionStateService PermissionState { get; set; } = null!;
}

子类使用示例

@if (PermissionState.IsApprover)
{
    <button>审批操作</button>
}

问题根源说明

  • 构造函数无法使用注入的ProtectedSessionStorage:Blazor的依赖注入在构造函数执行后完成,因此构造函数中无法访问注入服务。
  • OnInitializedAsync无需子类手动调用:Blazor生命周期会自动执行基类的该方法,仅需子类重写时记得调用基类实现。
  • 属性setter无法异步读取存储:setter没有合适的触发时机,且无法执行异步操作,因此无法完成赋值。

内容的提问来源于stack exchange,提问作者USMC6072

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:53:33