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
相关产品推荐
相关产品推荐

