1

我正在尝试实现这种模式

从调用者开始,我想做这样的事情:

var validatore = new Validator();

validatore.AddRule<TestRule>("OK");
validatore.AddRule<int>(45);

validatore.Validate();

规则的实施:

public interface IValidationRule<T>
{
    string Error { get; set; }
    bool Validate(T arg);
}

public class TestRule : IValidationRule<string>
{
    public string Error { get; set; }
    public bool Validate(string arg)
    {
        return arg == "test";
    }
}

问题是验证器的具体实现。我假设是这样的:

public interface IValidator
{
    void AddRule<TRule>(dynamic arg);
    ValidationResult Validate();
}

public class Validator : IValidator
{
    public void AddRule<T>(dynamic arg)
    {
        ???
    }

    public ValidationResult Validate()
    {
        forEach ...
    }
}

我应该将每个通用规则放在一个集合对象(AddRule)中的什么位置?我的实施方式是否正确?

4

1 回答 1

0

这个模式有点太抽象了。从某种意义上说,如果您从您想要做的事情开始,然后在此基础上进行抽象,那么您最终会得到更有用的概括。就像,在这种情况下,正在验证什么并不明显?某些 UI 中的用户输入?或者来自一些xml的数据?在第一种情况下,根据您的错误,您不仅需要一条错误消息,还可能需要一些更新 UI 的操作。然后验证抽象可能会采取完全不同的形式。实际代码从哪里来,进行验证?必须为每个验证规则实现特殊的类将产生一个糟糕的抽象,但当你真正想要使用它时,它会产生不必要的复杂代码。

另外,只有在绝对没有其他方法的情况下,我才会使用动态类型。

因此,假设您仍然感兴趣,下面的代码将用于验证引用类型。再说一次,如果您需要一个验证系统,您需要验证的值类型通常是某个类的属性,但请记住它不是通用的。

public class ValidationResult
{
    public bool HasError { get; set; } = false;
    public string ErrorText { get; set; } = "No error";
    public void SetError(string errorMsg)
    {
        this.HasError = true;
        ErrorText = errorMsg;
    }
}

public interface IValidationRule
{
    ValidationResult Validate();
}

public class ValidationRule<T> : IValidationRule
{
    private Func<T, ValidationResult> validatorFunc;
    private T validationSubject;
    public ValidationRule(T validationSubject, Func<T, ValidationResult> validatorFunc)
    {
        this.validationSubject = validationSubject;
        this.validatorFunc = validatorFunc;
    }

    public ValidationResult Validate() => validatorFunc?.Invoke(validationSubject);
}

public interface IValidator
{
    void AddRule<T>(T validationSubject, Func<T, ValidationResult> validationFunc);
    ValidationResult Validate();
}

public class Validator : IValidator
{
    private readonly List<IValidationRule> rules = new List<IValidationRule>();

    public void AddRule<T>(T validationSubject, Func<T,ValidationResult> validationFunc)
    {
        rules.Add(new ValidationRule<T>(validationSubject, validationFunc));
    }

    public ValidationResult Validate()
    {
        foreach (var rule in rules)
        {
            var result = rule.Validate();
            if (result.HasError) return result;
        }

        return new ValidationResult();
    }
}

要添加验证规则,您需要传入两个参数:稍后要验证的对象,以及包含逻辑并返回 ValidationResult 的 Func。像这样:

public class ValidatableObject
{
    public int intValue;
}

private void Test()
{
    var target = new ValidatableObject();
    target.intValue = 1;

    var validator = new Validator();
    validator.AddRule(target, (x) =>
    {
        var validationResult = new ValidationResult();
        if (x.intValue > 10) validationResult.SetError("Exceeds max value (10)");
        return validationResult;
    });

    log(validator.Validate().ErrorText);
    target.intValie = 100;
    log(validator.Validate().ErrorText);
}
于 2019-06-19T13:19:32.077 回答