C#一种可以返回多条消息的验证方法

时间:2010-10-14 10:10:50

标签: c#

在我继续保存到数据库之前,我需要检查一些事情。

如果我想将对象保存到数据库,我必须检查两件事:

  1. 是否填写了所有必需的东西?
  2. 是否已经有相同状态的东西?
  3. 如果其中一个要求失败,我想通知用户无法保存,因为条件1不符合,或条件2不符合或两个条件都不符合。

    我应该创建一个名为Validate()的方法并将文本消息放入return参数吗?像

    这样的东西
    public string Validate()
    {
      string message = string.Empty;
    
      if(! /*Do some validating for 1) */)
        message = "Condition 1 not met";
      if(! /*Do some validating for 2) */)
        message += Environment.NewLine + "Condition 2 not met!"; // 
    
      return message;
    }
    

    然后在调用代码中检查message是否为空。这是一个好方法吗?

    我一直在考虑两种方法。但是我必须在我想将对象保存到数据库的地方调用这两种方法。这样我就重复自己了。这样你会得到这样的东西:

    public bool AreRequiredThingsFilled()
    {
      if( /* do something*/ )
        return true;
    
      return false;
    }
    
    public bool CheckStatus()
    {
      if( /* do something*/ )
        return true;
    
      return false;
    }    
    

    然后我必须调用这两种方法,并且在调用代码中我必须设置要向用户显示的消息。

    我不知道应该采用哪种方式处理这种情况。这种情况有最好的做法吗?

8 个答案:

答案 0 :(得分:4)

我之前看过的一个有趣的模式是返回一个IEnumerable消息。

public bool HasValidationErrors()
{
    return GetValidationErrors().Any();
}

public IEnumerable<string> GetValidationErrors()
{
    if (/* Some Condition */)
    {
        yield return "condition 1 not met";
    }

    if (/* Some Condition */)
    {
        yield return "condition 2 not met";
    }

    yield break;
}

然后在你的代码中你会这样做:

if (HasValidationErrors())
{
    foreach (string error in GetValidationErrors())
    {
        // Do something with 'error'
    }
}

您可以返回错误对象而不是字符串。

答案 1 :(得分:1)

对于像Validate这样的通用方法,我宁愿返回collection

通常,如果我们谈论业务对象,则需要对其数据的各个方面进行多次验证。因此,验证应该返回一个集合,其中列出了遇到的所有错误。

调用者总是可以遍历集合,然后决定如何处理它。

虽然您可以根据自己的需要返回list<string>,但您可以考虑让custom object collection返回MessageCollection。这是因为有时候还会有其他数据要发回:例如:不同类型的错误类别/警告v / s错误等,或者OR条件等。

此外,根据是否需要对错误消息进行国际化,最好只返回实际业务对象中的错误代码,并让UI将其映射到正确的语言中,并以正确的语言为基础。用户的设置。

答案 2 :(得分:0)

第一个实施是维护噩梦。所有“客户端”代码都取决于你整合东西的方式。

第二个也不是首选;你将获得大量的公共方法来进行验证。

一个好的做法是将域逻辑作为POCO样式:创建一个保存所需信息状态的对象。让对象从具有通用验证方法的基类派生。让每个特定对象覆盖validate方法,并执行与该对象属性相关的一些特定验证。让每个验证方法在字符串列表中输出错误消息,例如List或IQueryable。

答案 3 :(得分:0)

我要么定义一个自定义的返回类型(消息集合),这是一个干净的解决方案。

或者作为一个快速的hackish解决方案返回一个bool并使用out参数输出附加信息。

bool Validate(out string[] messages)
{
    ...
}

bool Validate()
{
    string[] messages;
    return Validate(messages);
}

答案 4 :(得分:0)

我会使用现有的验证框架而不是自己做。

答案 5 :(得分:0)

在之前的项目中,我们有一个ValidationResult类。

public class ValidationResult
{
    public bool Success;
    public string Message;
}

这提供了一个简单的机制,用于返回验证是否成功以及发生相应的失败消息。如果我们的结果需要更多信息,我们只需继承ValidationResult并以这种方式扩展类。

答案 6 :(得分:0)

在要验证的对象上实现IDataErrorInfo,该接口允许收集由属性名称键入的错误消息。

它还有一个名为Error的字符串属性,它可以表示整个对象的单个错误。

答案 7 :(得分:0)

以下是我如何做到这一点......

  1. 我有一个通用的返回类型

    public class ValidatorResult
    {
        public ValidatorResult()
        {
            this.Failiures = new List<string>();
        }
    
        public bool IsValid => !this.Failiures.Any();
    
        public List<string> Failiures { get; set; }
    }
    
  2. 我创建了一个定义我的支票的界面......

    public interface ISalesOrderValidator
    {
        ValidatorResult ValidateParams(CreateSalesOrderParams obj);
    
        ValidatorResult ValidateParams(UpdateSalesOrderParams obj);
    
        ValidatorResult ValidateParams(ApplyDiscountParams obj);
    }
    
  3. ...和基类......

    public class BaseValidator
    {
        public BaseValidator()
        {
            this.ValidatorResult = new ValidatorResult();
        }
    
        public ValidatorResult ValidatorResult { get; set; }
    }
    
  4. 然后我实现了我的界面...

    public class SalesOrderValidator : BaseValidator, ISalesOrderValidator
    {
        ValidatorResult ValidateParams(CreateSalesOrderParams obj)
        {
            try
            {
                if (obj.Payee == null)
                    ValidatorResult.Failiures.Add("You must proivde a Payee");
    
                if (obj.PaymentAmount == 0)
                    ValidatorResult.Failiures.Add("PaymentAmount is 0");                
            }
            catch (Exception)
            {
                ValidatorResult.Failiures.Add("An unexpected error occurred.");
            }
    
            return base.ValidatorResult;
        }
    
        ValidatorResult ValidateParams(UpdateSalesOrderParams obj)
        {
            throw new NotImplementedException();
        }
    
        ValidatorResult ValidateParams(ApplyDiscountParams obj);
        {
            throw new NotImplementedException();
        }
    }
    
  5. 然后,在我需要进行检查的代码中,我调用了验证器......

     // start by doing some basic validation on the parameters
     var validationResult = _validator.ValidateParams(mySalesOrder);
     if (!validationResult.IsValid)
         throw new ValidationException(validationResult.Failiures.FirstOrDefault());
    
  6. ...这只是返回第一个错误 - 您可以更改代码以返回多个错误消息或错误堆栈(内部异常)。 注 - ValidationException定义如下......

        public class ValidationException : ApplicationException
        {
            public ValidationException()
            {
            }
    
            public ValidationException(string message)
                : base(message)
            {
            }
    
            public ValidationException(string message, Exception inner)
                : base(message, inner)
            {
            }
        }