验证错误层次结构设计

时间:2012-03-05 09:13:04

标签: c# oop validation class-hierarchy

在我们的系统中,我们有一个实体Product,它可能有各种自定义属性。属性集可能因产品而异,并存储在List<Property>类型的字段中。属性具有不同的类型(字符串,整数,双精度),并且可能具有一些特殊的特征,例如它们可能是多值的,可能是特定范围的值,来自给定列表的值等。属性的值始终包含在字符串字段Value中。

现在我当前的问题是实现这些属性的验证,我有点坚持采用什么方法来代表验证结果的代表。我必须满足的要求:      - 验证结果将由其他应用程序层使用,因此生成的API应清晰且易于使用      - 每个错误都应该有一个独特的表示      - API的用户应该有足够的信息来理解错误细节(例如,对于范围错误,应该提供最小可能值,最大可能值和实际值)

以下是我到目前为止所考虑的方法:

  1. 类层次结构。有一个基本抽象类ValidationError,每个特定错误都将反映在继承的类中。如果错误有任何细节,相应的类将具有存储所有信息的必要字段。例如:

    public abstract class ValidationError
    {
        // common fields and methods, if any
    }
    
    public class IncorrectFormatValidationError : ValidationError
    {
        // just empty class, nothing to add here
    }
    
    public class RangeValidationError : ValidationError
    {
        public object MinValue { get; set; }
    
        public object MaxValue { get; set; }
    }
    

    由于实际上空类的多样性,这种方法对我来说似乎是多余的。此外,使用这样的API似乎不对(if (typeof(error) == typeof(RangeValidationError)) - 胡说八道!)。然而,这是我想到的第一件事。

  2. 错误枚举,必要时还有类层次结构。所有错误都用枚举表示。在大多数情况下使用一个类ValidationError,当特定错误需要其他信息时,创建继承者,基本上与第一种方法相同。例如:

    public enum ValidationErrors
    {
        IncorrectFormat,
        ValueNotWithinRange,
        ...
    }
    
    public class ValidationError
    {
        public ValidationErrors ErrorType { get; set; } 
    
        public ValidationError(ValidationErrors type)
        {
            this.ErrorType = type;
            ...
        }
    
        // common fields and methods, if any
    }
    
    public class RangeValidationError : ValidationError
    {
        public object MinValue { get; set; }
    
        public object MaxValue { get; set; }
    
        public RangeValidationError(object minValue, object maxValue) :
            base(ValidationErrors.ValueNotWithinRange)
        {
            ...
        }
    }
    

    这种方法看起来好多了,但也有缺点。最大的一点就是我们作为API用户无法保证当我们遇到类型为ValueNotWithinRange的错误时,我们正在处理类型RangeValidationError的类,如果我们不是 - 我们怎么办?处理它?我想有一些设计级功能可以防止这种情况的存在,因为我不是开发API的onyl人。这种方法的另一个问题是,如果大多数错误最终都需要一些额外的信息,我们最终会得到相同的号码1。

  3. 任何人都有任何想法分享这两种方法或提出更好的方法吗?我将非常感谢任何回应。提前谢谢。

2 个答案:

答案 0 :(得分:0)

退一步并重新思考整个“代表验证错误的多个类”方法可能是一个好主意,因为它几乎可以保证您已经拥有验证器的层次结构< / em>的

任何验证错误都可以完美指定:

  1. 未能接受属性值的验证程序
  2. 物业名称
  3. 未能验证的值
  4. 任何进一步的信息(例如范围的限制,不匹配的正则表达式)已经出现在验证器实例上,并且可以通过它访问。

    那么只有一个看起来像这样的验证错误类呢:

    public sealed class ValidationError
    {
        public Validator Validator { get; set; }
        public string PropertyName { get; set; }
        public object AttemptedValue { get; set; }
    }
    

答案 1 :(得分:0)

您可能需要查看FluentValidation之类的内容。它轻巧,直观,涵盖了许多验证方案。

如果您对FluentValidation使用的验证结果不满意,您可以始终将它们包装在您自己的自定义验证错误类中。至少你会免费获得很多基本功能。