1

这与其说是如何做某事的问题,不如说是我如何更好地实施某事或以不同的方式思考问题。

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

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 年的开发经验,这并不多。但是,我觉得在做某事时,如果感觉有更好的方法,那么我可能没有正确或有效地做这件事就足够了。修改帐户标志会更改帐户列表中的对象。显然,将对象添加到新列表只会创建对该对象的引用。所以我不能做一些事情,比如持有 2 个集合,一个用于修改,另一个用于原始状态。我也无法进行深度复制,因为帐户类未标记为可序列化。由于对象的类型,我无法更改此设置。

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

4

1 回答 1

1

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

看看命令模式。这是一个代码项目链接,描述了如何实现它 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 操作

于 2013-10-10T10:54:45.673 回答