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

Postsharp Recordable与NotifyPropertyChanged:撤销时如何捕获属性变更?

解决撤销操作时属性变更无法被自定义切面捕获的问题

我明白你的困惑——手动修改属性时自定义切面能正常触发,但执行撤销操作时却没反应,这确实容易让人摸不着头脑。核心原因在于PostSharp的Recordable机制在执行撤销/重做时,并没有走常规的属性setter路径,而是直接修改对象的底层字段来恢复值,以此避免循环调用和提升性能,所以你用OnLocationSetValueAdvice拦截属性setter的逻辑自然就捕获不到这个过程了。

那该怎么解决呢?推荐你用PostSharp提供的IUndoRedoAware接口,它专门用来处理撤销和重做事件,能完美覆盖你需要的场景:

具体实现步骤

  1. 让你的实体类实现IUndoRedoAware接口,这个接口包含Undo和Redo两个方法,分别对应撤销和重做操作触发时的回调。
  2. 在这两个方法里,你可以通过UndoRedoEventArgs参数获取到本次操作涉及的所有属性变更,然后执行你的自定义脏数据检测逻辑。

举个简单的代码示例:

// 确保你的类已经标记了Recordable和NotifyPropertyChanged切面
[Recordable]
[NotifyPropertyChanged]
public class YourEntity : INotifyPropertyChanged, IUndoRedoAware
{
    // 你的属性定义
    public string YourProperty { get; set; }

    public void Undo(UndoRedoEventArgs e)
    {
        // 遍历本次撤销涉及的所有属性变更
        foreach (var change in e.Changes)
        {
            var changedProperty = change.PropertyName;
            // 执行你的脏数据检测逻辑,比如标记属性为脏
            HandlePropertyChange(changedProperty);
        }
    }

    public void Redo(UndoRedoEventArgs e)
    {
        // 重做操作同理处理
        foreach (var change in e.Changes)
        {
            HandlePropertyChange(change.PropertyName);
        }
    }

    private void HandlePropertyChange(string propertyName)
    {
        // 这里写你的自定义脏数据检测逻辑
        Console.WriteLine($"属性 {propertyName} 在撤销/重做时发生变更");
    }
}

额外说明

  • 如果你需要更细粒度的控制,比如针对单个属性的撤销行为,还可以结合Recordable的变更跟踪功能,在Undo方法里判断具体属性后再执行对应逻辑。
  • 这种方式是PostSharp官方推荐的处理撤销/重做自定义逻辑的方案,比试图拦截字段修改要更稳定、更符合框架设计。

内容的提问来源于stack exchange,提问作者klawusel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:49:27