如何在XPO类中定义创建后不可修改的只读持久化属性?
在XPO中定义创建后只读的持久化属性
在XPO里实现这种创建后只读、同时支持持久化的属性,有几个实用的方案,我给你挨个说明:
方案1:私有Setter+新建状态校验
这种方式兼顾灵活性和安全性,外部无法直接修改属性,同时只允许在对象新建时初始化值:
public class Order : XPObject { // 必须保留带Session参数的构造函数 public Order(Session session) : base(session) { } private string _orderNumber; // 标记为持久化属性 [Persistent] public string OrderNumber { get { return _orderNumber; } // 私有Setter,外部无法访问 private set { _orderNumber = value; } } // 提供初始化方法,仅允许在对象未保存时设置值 public void InitializeOrderNumber(string orderNum) { // IsNewObject判断对象是否为新建状态(未持久化到数据库) if (IsNewObject) { OrderNumber = orderNum; } else { throw new InvalidOperationException("订单编号只能在创建时设置"); } } }
为什么好用:
[Persistent]标记确保XPO会把这个属性持久化到数据库- 私有Setter从语法层面限制外部修改
IsNewObject校验保证只有刚创建的对象能设置值,避免后续修改
方案2:无Setter+构造函数直接赋值
如果需要最严格的限制,连内部不小心修改的可能都要杜绝,可以用这种方式:
public class Customer : XPObject { private string _customerCode; // 带初始化参数的构造函数,创建时直接给私有字段赋值 public Customer(Session session, string initialCustomerCode) : base(session) { _customerCode = initialCustomerCode; } // 仅保留Getter的属性,通过[Persistent]绑定到私有字段 [Persistent("_customerCode")] public string CustomerCode { get { return _customerCode; } } }
优势:
- 属性完全没有Setter,任何地方都无法通过属性修改值
- 只能通过构造函数在对象创建时初始化,彻底杜绝修改可能
[Persistent("_customerCode")]明确指定持久化的字段名,XPO会正常存储和读取
方案3:重写生命周期方法做校验(兜底方案)
如果需要在内部也严格管控属性修改,可以通过重写XPO的生命周期方法做额外校验,作为兜底:
public class Product : XPObject { private string _productSKU; private string _originalSKU; public Product(Session session) : base(session) { } [Persistent] public string ProductSKU { get { return _productSKU; } set { // Setter里先校验,非新建状态不允许修改 if (!IsNewObject && _productSKU != value) { throw new InvalidOperationException("SKU属性不可修改"); } _productSKU = value; } } protected override void OnLoaded() { base.OnLoaded(); // 加载对象时保存原始值 _originalSKU = _productSKU; } protected override void OnSaving() { base.OnSaving(); // 保存前再次校验,防止内部绕过Setter修改字段 if (!IsNewObject && _productSKU != _originalSKU) { throw new InvalidOperationException("只读属性SKU不允许修改"); } } }
适用场景:
- 适合需要在内部也严格限制属性修改的场景
- 双重校验(Setter+OnSaving)能最大程度避免意外修改
- 缺点是代码相对繁琐,一般作为前两种方案的补充
内容的提问来源于stack exchange,提问作者Alavi
相关产品推荐
相关产品推荐

