如何简化验证检查代码?

时间:2011-12-14 09:55:55

标签: c#

我有验证代码:

public IDictionary<string, string> ValidateForDeletion(Account ac)
        {
            var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
            if (account == null)
            {
                _errors.Add("", "Account does not exist");
                return _errors;
            }
            if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
            {
                _errors.Add("", "Account contains products");
                return _errors;
            }
            return _errors;
        }

我看到有很多“return _errors”行。有什么方法可以整理代码并保留功能吗?我看到了一个使用yield的例子,但不确定我是否可以将其用于此方法。

5 个答案:

答案 0 :(得分:1)

public IDictionary<string, string> ValidateForDeletion(Account ac)
{
    var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
    if (account == null)
    {
        _errors.Add("", "Account does not exist");
    }
    else if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
    {
        _errors.Add("", "Account contains products");
    }
    return _errors;
}

这将消除您的多个返回语句

答案 1 :(得分:0)

嗯,你总是可以把额外的东西拉到自己的方法中:

public IDictionary<string, string> ValidateForDeletion(Account ac)
{
  var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
  return BuildErrorsList(account);
}

private IDictionary<string, string> BuildErrorsList(Account account)
{
  if (account == null)
     _errors.Add("", "Account does not exist");
  if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
      _errors.Add("", "Account contains products");
  return _errors;
}

好的准则是每个方法都应该在一个抽象层次上工作,否则你可能想把“低层次”的东西拉到自己的方法中。

答案 2 :(得分:0)

public IEnumerable<ValidationResult> ValidateForDeletion(Account ac)
{
    var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
    if (account == null)
    {
        yield return new ValidationResult("Account does not exist");
    }
    if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
    {
        yield return new ValidationResult("Account contains products");
    }
}

答案 3 :(得分:0)

  1. 你的方法改变状态(_errors字段)同时返回字段并不理想 - 这使得它有点混乱。通常你会有一个改变状态的方法(更改_errors有一个返回结果的函数。

  2. ValidateForDeletion方法在第一次失败后返回,而不是将所有错误添加到字典中。你确定这是正确的行为吗?

  3. 如果重构这个,我可能会摆脱ValidateForDeletion的副作用(对字段的更改)并让它返回IEnumerable<string>。我还会让它执行完整的验证集。显然这会对调用代码产生影响,因此您必须确保不会破坏任何内容。

    public IEnumerable<string> ValidateForDeletion(Account ac)
    {
        var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
        if (account == null)
        {
            yield return "Account does not exist";
        }
    
        if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
        {
            yield return "Account contains products";
        }
    
        return;
    }
    

答案 4 :(得分:0)

你可以做类似收益的事情。如果您考虑通过引用传递,则可以在对象或存储库中包含验证代码。

例如,我正在验证是否可以删除帐户,我可以在具有此方法的Account上使用IValidateDelete接口:

bool account.IsValidForDeletion(ref ValidationErrors validationErrors);

然后我可以调用它并传入我的空验证错误方法。如果结果是真的,你很高兴。如果为false,则会将验证错误附加到ValidationErrors对象的内部列表中。

public bool IsValidForDeletion(ref Validationerrors validationErrors)
{
//
if (something is valid)
{
  return true;
}

validationErrors.AddError("Something is wrong, this cannot be deleted");

return false;
}

现在你可以像这样运行所有方法:

public ValidationErrors ValidateABunchOfStuff()
{
   ValidationErrors errors = new ValidationErrors();

   account.IsValidForDeletion(errors);
   product.IsValidForDeletion(errors);
   cake.IsValidForDeletion(errors);

   return errors;
}