如何将Cookie用作Base Controller属性的后备存储?
问题根源
你当前的写法里,UserPreferences是引用类型,当通过UserPreferences属性获取对象时,拿到的是该对象的内存引用。直接修改PageSize这类子属性,只是修改了引用指向的对象内部数据,不会触发BaseController中UserPreferences属性的setter,自然也就不会调用CookieManager去更新Cookie。
另外先修正你代码里的语法错误:UserPreferences类的属性定义存在笔误,应该是int类型,不是string int。
解决方案
方案1:添加显式的更新方法(最简单直接)
在BaseController里新增一个方法,专门用来更新用户偏好并同步到Cookie。修改子属性后,调用这个方法完成Cookie更新:
public class UserPreferences { public int PageSize { get; set; } public int ThemeId { get; set; } } public class BaseController : Controller { protected readonly CookieManager _cookieManager; private UserPreferences _cachedPreferences; // 缓存偏好对象,避免重复从Cookie读取 public UserPreferences UserPreferences { get { if (_cachedPreferences == null) { _cachedPreferences = _cookieManager.GetUserPreferences(); } return _cachedPreferences; } } // 新增显式更新方法 protected void SaveUserPreferences() { _cookieManager.SetUserPreferences(_cachedPreferences); } } public class HomeController : BaseController { public ActionResult Index() { UserPreferences.PageSize = 10; // 显式调用保存方法更新Cookie SaveUserPreferences(); return View(); } }
方案2:将UserPreferences设为不可变类型,修改时创建新对象
强制修改偏好时必须生成新的对象实例,这样就能触发setter完成Cookie更新:
// 不可变记录类,所有属性只读,通过构造器初始化 public record UserPreferences(int PageSize, int ThemeId); public class BaseController : Controller { protected readonly CookieManager _cookieManager; public UserPreferences UserPreferences { get => _cookieManager.GetUserPreferences(); set => _cookieManager.SetUserPreferences(value); } } public class HomeController : BaseController { public ActionResult Index() { // 创建新的实例,触发setter更新Cookie UserPreferences = UserPreferences with { PageSize = 10 }; return View(); } }
这里用了C#的记录类型(record)和with表达式,简化不可变对象的更新操作。如果使用普通类,需要手动编写构造器和属性复制逻辑。
方案3:通过INotifyPropertyChanged自动监听属性变化(复杂但自动化)
给UserPreferences实现INotifyPropertyChanged接口,然后在BaseController里订阅属性变化事件,自动同步到Cookie:
using System.ComponentModel; using System.Runtime.CompilerServices; public class UserPreferences : INotifyPropertyChanged { private int _pageSize; private int _themeId; public int PageSize { get => _pageSize; set { _pageSize = value; OnPropertyChanged(); } } public int ThemeId { get => _themeId; set { _themeId = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class BaseController : Controller { protected readonly CookieManager _cookieManager; private UserPreferences _userPreferences; public UserPreferences UserPreferences { get { if (_userPreferences == null) { _userPreferences = _cookieManager.GetUserPreferences(); // 订阅属性变化事件 _userPreferences.PropertyChanged += UserPreferences_PropertyChanged; } return _userPreferences; } } private void UserPreferences_PropertyChanged(object sender, PropertyChangedEventArgs e) { // 属性变化时自动更新Cookie _cookieManager.SetUserPreferences(_userPreferences); } } public class HomeController : BaseController { public ActionResult Index() { // 修改子属性会自动触发Cookie更新 UserPreferences.PageSize = 10; return View(); } }
这个方案适合需要频繁修改子属性且不想每次手动调用保存的场景,但会增加代码复杂度。
内容的提问来源于stack exchange,提问作者user3953989
相关产品推荐
相关产品推荐

