c# - 验证策略

标签 c# design-patterns

我有一个包含许多类的业务模型,该模型中的一些逻辑实体由许多不同的类(父-子-孙)组成。在这些不同的类上,我定义了不变的约束,例如composite 应该有一个 Code 值。

我目前让每个类都实现一个这样的接口(interface)...

public interface IValidatable
{
    IEnumerable<ValidationError> GetErrors(string path);
}

如果未设置 Code,父级将添加一个验证错误,然后对每个子级执行 GetErrors,这将依次对每个孙级调用 GetErrors。

现在我需要为不同的操作验证不同的约束,例如

  1. 应该始终检查某些约束,因为它们是不变的
  2. 当我想在根上执行操作 X 时,应该检查一些约束。
  3. 执行操作 Y 时可能会检查一些额外的约束。

我考虑过向 GetErrors 方法添加一个“Reason”参数,但出于某种原因,我不能完全指出这感觉不对。我还考虑过创建一个访问者并有一个具体的实现来验证 OperationX 和另一个 OperationY 但不喜欢这个,因为多个操作需要一些约束检查但不是所有操作都需要(例如 OperationX + OperationY 需要日期)但不是 OperationZ),我不想重复检查的代码。

如有任何建议,我们将不胜感激。

最佳答案

这里存在绝缘问题,因为您的类负责进行自己的验证,但该验证的性质取决于您正在执行的操作类型。这意味着类需要知道可以对它们执行的操作类型,这在类和使用它们的操作之间创建了相当紧密的耦合。

一种可能的设计是像这样创建一组并行的类:

public interface IValidate<T>
{
    IEnumerable<ValidationError> GetErrors(T instance, string path);
}

public sealed class InvariantEntityValidator : IValidate<Entity>
{
    public IEnumerable<ValidationError> GetErrors(Entity entity, string path)
    {
        //Do simple (invariant) validation...
    }
}

public sealed class ComplexEntityValidator : IValidate<Entity>
{
    public IEnumerable<ValidationError> GetErrors(Entity entity, string path)
    {
        var validator = new InvariantEntityValidator();
        foreach (var error in validator.GetErrors(entity, path))
            yield return error;

        //Do additional validation for this complex case
    }
}

您仍然需要解决如何将验证类与正在验证的各种类相关联的问题。听起来这应该以某种方式发生在操作级别,因为这是您知道需要进行哪种类型的验证的地方。如果没有更好地了解您的架构,很难说。

关于c# - 验证策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6599501/

相关文章:

c# - LogicalTreeHelper.GetChildren - ObservableCollection Move() 导致 DataTemplate 中的 ContentControl 丢失其内容?

c# - 在 C# 应用程序中获取 Transact SQL 查询结果

c# - 如何检测斑马打印机是否安装

C#/XAML Tapped 事件

Java——模式——Matcher.group()?

c# - IIS 输出缓存 - 如何将资源添加到缓存,无论路径如何

java - 什么是针对接口(interface)编程而不是针对实现编程

java - 样板文件太多,如何减少我的 POJO 构建器?

java - 复制和增强对象的最佳实践(设计模式)

python - 在 python 中实现服务提供者接口(interface)模式