.NET 5 Blazor LocalStorage 重启应用后读取已存值始终为false问题
问题根因
- 核心问题出在
ItemUiBehaviour类的属性访问修饰符配置:类中3个布尔属性的set访问器均为私有(private) - Blazor生态常用的LocalStorage操作库(包括Blazored.LocalStorage、微软官方提供的ProtectedLocalStorage)默认采用
System.Text.Json组件完成对象和JSON字符串的序列化/反序列化转换,该组件默认仅允许对公共可写属性执行反序列化赋值,私有set的属性不会被反序列化器修改,因此读取生成的新实例中所有布尔值都会保留类型默认值false - 单次应用运行周期内读写正常的原因:大部分LocalStorage库会默认开启内存缓存机制,同一会话下写入后的对象会被缓存到内存中,后续读取操作会直接返回内存中的已有实例,不会触发反序列化流程,因此功能表现正常;应用重启后内存缓存清空,读取操作会从浏览器LocalStorage中拉取JSON字符串重新反序列化生成新实例,此时私有set属性无法被赋值,就会出现所有布尔属性都为false的异常表现。
修复方案
以下方案任选其一即可:
方案1:修改属性为公共可写
直接调整属性的set访问器修饰符,让序列化器可以直接赋值,修改成本最低:
public bool Show { get; set; } public bool Enabled { get; set; } public bool AutoRefresh { get; set; }
方案2:添加序列化特性保留封装性
如果需要保留私有set的封装逻辑,可给对应属性添加[JsonInclude]特性,强制System.Text.Json反序列化时写入私有set属性:
using System.Text.Json.Serialization; namespace Company.Data { public class ItemUiBehaviour { [JsonInclude] public bool Show { get; private set; } [JsonInclude] public bool Enabled { get; private set; } [JsonInclude] public bool AutoRefresh { get; private set; } // 原有方法无需修改 public void ToggleShow() { Show = !Show; } public void SetShow(bool show) { Show = show; } public void SetEnabled(bool enabled) { Enabled = enabled; } public void SetAutoRefresh(bool autoRefresh) { AutoRefresh = autoRefresh; } public void ToggleEnable() { Enabled = !Enabled; } public void ToggleAutoRefresh() { AutoRefresh = !AutoRefresh; } } }
方案3:全局配置序列化规则
如果不想修改原有类的代码,可在注册LocalStorage服务时全局配置序列化规则,允许反序列化器写入非公共setter:
// 以Blazored.LocalStorage为例,Program.cs中注册服务时添加配置 builder.Services.AddBlazoredLocalStorage(config => { config.JsonSerializerOptions.PropertyVisibilityFilter = (prop, _) => prop.SetMethod != null; });
内容的提问来源于stack exchange,提问作者polonskyg
相关产品推荐
相关产品推荐

