在循环中调用具有相同输出和不同输入的多个方法

Moh*_*ari 5 c# design-patterns

我有多种方法,具有不同的输入参数和相同的输出.

我使用输入类型的数字调用Method1,然后检查其结果,如果结果有效,则调用下一个方法(此时输入类型为字符串),依此类推.

在这个例子中我有三种方法,但如果我有10种方法或20种方法具有不同的输入和相同的输出我必须写冗余代码,我该如何防止这些冗余代码?

这是方法的示例:

public ValidationResult Method1(int number, string family)
{
    var validationResult = new validationResult();
    if(number > 10 || family="akbari")
    {
        validationResult.Errors.Add(new ValidationFailure("", "Invalid Number"));
    }
    return validationResult;
}

public ValidationResult Method1(string name)
{
    var validationResult = new validationResult();
    if(name.Length > 20)
    {
        validationResult.Errors.Add(new ValidationFailure("", "Invalid name"));
    }
    return validationResult;
}

public ValidationResult Method1(double average, string family)
{
    var validationResult = new validationResult();
    if(average < 14)
    {
        validationResult.Errors.Add(new ValidationFailure("", "Invalid average"));
    }
    return validationResult;
}
Run Code Online (Sandbox Code Playgroud)

我称这种方法如下:

var validationResult = Method1(20, "test");
if (!validationResult.IsValid)
{
    return validationResult.FirstError();
}
validationResult = Method2("Samsung");
if (!validationResult.IsValid)
{
    return validationResult.FirstError();
}   
validationResult = Method3(15.5);

if (!validationResult.IsValid)
{
    return validationResult.FirstError();
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*art 3

(另请检查下面的替代解决方案!)

var valMethods = new List<Func<ValidationResult>>
{
    ()=>Method1(number,family),
    ()=>Method2(name),
    // ...
};

foeach(var valMethod in valMethods)
{
    var valResult = valMethod();
    if (!valResult.IsValid)
    {
        return valResult.Errors.First();
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,这会给委托带来一些性能损失,并且由于您需要参数,因此很难将其放置在外部,例如返回委托的方法中。

作为替代方案,您可以创建一个值包作为参数(可能是具有适当接口的调用类),这对于所有方法都是相同的,并且每个方法都会选择它需要的内容(这反过来又使验证方法更少清除)。

另一种选择是只返回 bool 值并将验证详细信息保留在单独的对象中,可能实现验证的扩展方法(另请检查 Myleo 的谓词答案):

internal static class ValidationMethods
{
    public static bool CheckIsValid1(this IList<ValidationResult> valResults, int number, string family)
    {
        var validationResult = new validationResult();
        if(number > 10 || family="akbari")
        {
            validationResult.Errors.Add(new ValidationFailure("", "Invalid Number"));
        }
        valResults.Add(validationResult);
        return validationResult.IsValid;
    }

    public static bool CheckIsValid2(this IList<ValidationResult> valResults, string name)
    {
        // next check ...
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在验证代码中:

var valResults = new List<ValidationResult>();
if (!valResults.CheckIsValid1(number, family)
    || !valResults.CheckIsValid2(name)
    || // more checks... will stop if one fails
    )
{
    return valResults.Last().Errors.First();
}
Run Code Online (Sandbox Code Playgroud)

这样,您就不必与代表打交道。当第一次失败时检查停止(|| 或条件检查在第一次成功时停止,此处为否定的 IsValid)。并且您的 valResults 仍然包含验证数据。

从您的代码来看,简单地使用异常也可能是可行的。如果错误频繁发生,那么这种无异常验证可能是必要的,并且异常会降低性能,但如果错误是异常的,那么请随意使用异常!