【问题标题】:Writing a maintainable commit method编写可维护的提交方法
【发布时间】:2010-12-08 17:38:36
【问题描述】:

我有一个 ViewModel 封装了一些正在选项对话框中编辑的属性。在他们点击 Ok 按钮之前,我实际上无法将它们保存到设置中,这最终会在这个特定的 ViewModel 上调用 Commit。

我的 ViewModel 中的单个属性如下所示:

public bool SomeProperty
{
    get
    {
        return m_SomeProperty;
    }
    set
    {
        if (m_SomeProperty != value)
        {
            m_SomeProperty = value;
            NotifyPropertyChanged("SomeProperty");
        }
    }
}
private bool m_SomeProperty = Properties.Settings.Default.SomeProperty;

所以 Commit 的正常实现是这样做的:

public void Commit()
{
    Properties.Settings.Default.SomeProperty = m_SomeProperty;
    // Add other properties here...
}

这还不错,但我不喜欢这样的原因是如果你添加一个新属性,你必须在两个地方为它添加代码。我尽量避免这种情况。

起初我以为我可以声明一个名为 OnCommit 的私有事件并让 Commit 方法引发该事件,并让每个属性的代码为该事件添加一个事件处理程序并在那里写入设置,但我没有'不知道如何在构造函数中不添加事件处理程序的情况下做到这一点,这对这种情况没有帮助。

有什么想法吗?有没有人有一种优雅的方式来做我想做的事情?

编辑:感谢六字母变量的回答。我采纳了这个想法并将其纳入SoapBox Core 并将结果开源。查看选项对话框以了解其工作原理。

【问题讨论】:

    标签: c# events properties settings


    【解决方案1】:

    也许维护一个Actions 的列表来执行?

    private List<Action> commitActions = new List<Action>();
    
    public bool SomeProperty
    {
        get
        {
            return m_SomeProperty;
        }
        set
        {
            if (m_SomeProperty != value)
            {
                m_SomeProperty = value;
                lock (commitActions)
                {
                    commitActions.Add(
                        () => Properties.Settings.Default.SomeProperty = value);
                }
                NotifyPropertyChanged("SomeProperty");
            }
        }
    }
    

    然后更新您的 Commit 代码以循环执行操作。

    public void Commit()
    {
        List<Action> commits;
        lock (commitActions)
        {
            commits = new List<Action>(commitActions);
            commitActions.Clear();
        }
    
        foreach (var commit in commits)
        {
            commit();
        }
    }
    

    【讨论】:

    • 这是一个非常酷的想法。我意识到取消操作也需要它(将它们重置为保存的值)。不过有个问题,如果我只从 GUI 访问它,我需要锁吗?
    • 如果你真的只有一个线程访问commitActions,那么你不需要锁。如果代码涉及更多,锁定只是一个建议。此外,您可以考虑创建自己的 Undo/Redo 类,其中包含 Action 用于撤消和重做发生的任何事情。
    • 没错,但这仅适用于应用程序设置,所以我真的不需要撤消和重做。我实际上是在模型级别处理撤消和重做,因为它们都是作为不可变类实现的,所以我可以只保留最后 X 个世界对象的堆栈/队列。不过谢谢,这是完美的。
    【解决方案2】:

    您能否使用反射来确定您的类具有哪些属性并遍历它们?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-14
      • 2019-12-06
      • 1970-01-01
      • 2021-05-25
      • 2010-12-14
      • 1970-01-01
      • 2016-03-14
      • 2017-08-01
      相关资源
      最近更新 更多