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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:40:46