我有一个方法可以通过方法链非常巧妙地编写:
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");
答案 0 :(得分: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(...);
答案 1 :(得分: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()
以实现结果。
答案 2 :(得分:1)
考虑使用Code Contracts(例如,将后置条件添加到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();