使用undo修改集合中的类

时间:2013-03-27 12:20:02

标签: c# collections undo

这不是一个关于如何做某事的问题,而是我如何更好地实现某些事情或以不同的方式思考问题。

我有一个winforms应用程序,允许用户在网格中选择多行。这些行表示帐户,当用户选择帐户并点击按钮时,对象上的布尔属性将更改为所选值的任何值,而不管其现有状态如何。但是,如果验证方法失败,则会向用户发送一条消息,并且需要将boolean属性设置回其原始状态。

public void ModifyAccounts(List<DemoAccount> accts, bool updateIsSpecial)
{
    // Dictionary that will hold the account ID along with the booleans original state
    Dictionary<int, bool> originalState = new Dictionary<int, bool>();
    foreach(var acct in accts)
    {
        // Add the current state to the dictionary
        originalState.Add(acct.Id, acct.IsSpecial);

        acct.IsSpecial = updateIsSpecial;
    }

    // Send the list to another method that loops through each account and checks
    // for specific validation rules. Returns a collection of tuples. The tuple
    // contains the account for item1 and a bool validated flag for item2
    var valAccounts = ValidateAccounts(accts);

    var failedAccounts = from obj in valAccounts
                         where !acct.Item2
                         select new
                                  {
                                      account = obj.Item1,
                                      isValid = obj.Item2
                                  };

    if (failedAccounts.Count() > 0)
    {
        // Alert the user with custom msg box method that the accounts failed
        // Do Custom Method

        // Reset the values of the failed accounts to their previous state. 
        // It is possible that some accounts passed validation and were saved,
        // only the failed accounts should be reset. 
        foreach (var obj in failedAccounts)
        {
            bool originalFlagState = false;
            originalFlagStates.TryGetValue(obj.account.Id, out originalFlagState);
            var origAccount = accts.Where(x => x.Id == obj.account.Id).FirstOrDefault();
            origAccount.IsSpecial = originalFlagState;

        }
    }
}

我希望这不会太混乱。我只有3年的开发经验,这不是很多。但是,我觉得在理解某些事情的时候就足够了解如果感觉有更好的方式,那么我可能没有正确或有效地做到这一点。修改帐户标志会更改帐户列表中的对象。显然,将对象添加到新列表只会创建对该对象的引用。所以我不能做一些事情,比如拿一个集合进行修改,另一个进行原始状态。我也无法进行深层复制,因为帐户类未标记为可序列化。由于对象的类型,我无法改变这一点。

感谢任何能提供一些建议或见解的人!

1 个答案:

答案 0 :(得分:1)

我不明白为什么要在更改之后验证,而不是事先验证。 但是如果你真的必须验证并在之后使用撤销,那么有一种支持这种行为的设计模式

查看命令模式。这是一个代码项目链接,描述了如何实现它 http://www.codeproject.com/Articles/8303/Using-the-Command-pattern-for-undo-functionality

在您的特定情况下,我将遍历命令堆栈并撤消所有在失败帐户上使用的命令

它可能看起来像这样

    foreach (var obj in failedAccounts)
         foreach ICommand command in commandStack
              If(command.element.Equals(obj))
                   command.undo;

command.element应该包含您要用命令更改的元素。

如果你不想要两个foreach,你可以使用System.Linq操作