2012-06-07 31 views
6

我有這可以通過方法鏈接很整齊地寫一個方法:LINQ方法鏈和精細錯誤處理

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"); 

回答

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(...); 
+0

這看起來不錯。考慮到錯誤檢查的本質,我懷疑它可能不需要泛型方法(即通常錯誤檢查的性質是特定於給定類型的)。有一個擴展方法只是返回未經修改的輸入的一般方法正是需要的。 – Chris

+0

你說得對。我添加了一個更通用的'Validate'方法,在這種情況下,泛型是必需的。 –

+0

不錯。我希望我可以再次爲這個不錯的小驗證功能+1。 :) – Chris

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()以實現結果。

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(); 
+0

這聽起來很理想。但在我的特殊情況下,數據需要符合某些期望,所以靜態分析無法幫助(但我意識到這也提供了運行時檢查,但不確定採用這種新方法並使用新工具在我的給予這種情況)。當條件不滿意時,我能夠注入自己的邏輯嗎?我真的需要更多地關注這個! – Clafou

+0

我的意思是允許我提供有用的特定異常而不是泛型異常類型的邏輯,從而使我的調用代碼更容易處理可恢復的錯誤。 – Clafou

+0

@Clafou,你想要注入什麼邏輯之王?違反合同會帶來一個'ContractException'。你可以解決的。 – Dennis