6

我有一个可以通过方法链很好地编写的方法:

return viewer.ServerReport.GetParameters()
    .Single(p => p.Name == Convention.Ssrs.RegionParamName)
    .ValidValues
    .Select(v => v.Value);

但是,我希望能够在每个点进行一些检查,因为如果任何链接方法返回意外结果,我希望提供有用的诊断信息。

为了实现这一点,我需要打破我所有的链接,并在每个调用后面加上一个if块。它使代码的可读性降低了很多。

理想情况下,我希望能够编织一些链式方法调用,这将允许我在每个点处理意外结果(例如,抛出一个有意义的异常,例如new ConventionException("The report contains no parameter")第一个方法返回一个空集合)。任何人都可以提出一个简单的方法来实现这样的事情吗?

编辑:

这是使用@JeffreyZhao 的答案的结果:

return viewer.ServerReport.GetParameters()
    .Assert(result => result.Any(), "The report contains no parameter")
    .SingleOrDefault(p => p.Name == Convention.Ssrs.RegionParamName)
    .Assert(result => result != null, "The report does not contain a region parameter")
    .ValidValues
    .Select(v => v.Value)
    .Assert(result => result.Any(), "The region parameter in the report does not contain any valid value");
4

3 回答 3

7

也许你可以使用这种方法。

static T Check<T>(this T value)
{
    if (...) throw ...;

    return value;
}

然后:

xxx.Single(...).Check().Select(...).Check()...

更新:

你甚至可以:

static T Validate<T>(this T value, Func<T, bool> validate, string errorMessage)
{
    if (!validate(value)) 
        throw new ValidationFailedException(errorMessage);

    return value;
}

然后:

xxxx.Single()
    .Validate(v => v > 0, "Must be greater than zero")
    .NextStep()
    .Validate(...);
于 2012-06-07T10:18:38.253 回答
1

考虑使用代码契约(例如添加后置条件以ServerReport.GetParameters确保方法不会返回空集合)。它们允许以更优雅的方式做你想做的事,而不是编写你自己的检查逻辑。

class ReportParameter { }
class ServerReport
{
    public ReportParameter[] GetParameters()
    {
        Contract.Ensures(Contract.Result<ReportParameter[]>() != null && Contract.Result<ReportParameter[]>().Length > 0,
            Resource1.Oops);

        // here's some logic to build parameters array...
        return new ReportParameter[0];
    }
}

用法:

// Oops! I need at least one parameter!
var parameters = new ServerReport().GetParameters();
于 2012-06-07T10:33:26.117 回答
1

您可以使用局部变量轻松地将过程拆分为单独的步骤:

var result1 = viewer.ServerReport.GetParameters();
var result2 = result1.Single(p => p.Name == Convention.Ssrs.RegionParamName);
var result3 = result2.ValidValues;
var result4 = result3.Select(v => v.Value);
return result4;

现在您可以在步骤之间进行任何您想要的检查。

但是请注意,某些结果实际上并没有做任何工作。例如,最后一步不会产生一个列表作为结果,它会产生一个从 读取的枚举ValidValues,因此当您使用结果时,该步骤中的任何错误都会发生,而不是在此方法中。您可能希望.ToList()在某些步骤的末尾添加以实现结果。

于 2012-06-07T10:25:15.900 回答