2012-06-07 38 views
6

Tôi có một phương pháp mà có thể được viết khá gọn gàng qua phương pháp chaining:LINQ phương pháp chaining và lỗi hột xử lý

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

Tuy nhiên tôi muốn để có thể làm một số kiểm tra tại mỗi điểm như tôi muốn cung cấp thông tin chẩn đoán hữu ích nếu bất kỳ phương pháp xích nào trả về kết quả không mong muốn.

Để đạt được điều này, tôi cần phải chia nhỏ tất cả chuỗi và theo dõi từng cuộc gọi với khối if. Nó làm cho mã dễ đọc hơn rất nhiều. Lý tưởng nhất là tôi muốn có thể dệt trong một số cuộc gọi phương thức xích cho phép tôi xử lý các kết quả không mong muốn tại mỗi điểm (ví dụ: ném một ngoại lệ có ý nghĩa như new ConventionException("The report contains no parameter") nếu phương thức đầu tiên trả về một bộ sưu tập trống). Bất cứ ai có thể đề xuất một cách đơn giản để đạt được một điều như vậy?

Edit:

Đây là kết quả của việc sử dụng @ câu trả lời JeffreyZhao của:

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

Trả lời

7

lẽ bạn có thể sử dụng phương pháp này.

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

    return value; 
} 

thì:

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

Cập nhật:

Bạn thậm chí có thể:

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

    return value; 
} 

thì:

xxxx.Single() 
    .Validate(v => v > 0, "Must be greater than zero") 
    .NextStep() 
    .Validate(...); 
+0

này có vẻ tốt. Và với bản chất của việc kiểm tra lỗi, tôi nghi ngờ có thể là các phương thức chung sẽ không cần thiết (nghĩa là bản chất của kiểm tra lỗi là cụ thể đối với một kiểu đã cho). Cách tiếp cận chung của việc có một phương thức mở rộng mà chỉ trả về đầu vào chưa được sửa đổi mặc dù chính xác là cái cần thiết. – Chris

+0

Bạn nói đúng.Tôi đã thêm một phương thức 'Validate' tổng quát hơn và trong trường hợp đó thì generic là bắt buộc. –

+0

Rất đẹp. Tôi ước tôi có thể +1 nó một lần nữa cho chức năng 'Validate' nhỏ đẹp đó. :) – Chris

1

Bạn có thể dễ dàng chia quá trình này trong các bước riêng biệt với các biến địa phương:

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; 

Bây giờ bạn có thể làm bất kỳ kiểm tra bạn muốn giữa các bước.

Lưu ý rằng một số kết quả không thực sự thực hiện bất kỳ tác phẩm nào. Bước cuối cùng ví dụ không tạo ra một danh sách như là kết quả, nó tạo ra một enumerable mà đọc từ ValidValues, do đó, bất kỳ lỗi nào trong bước đó sẽ xảy ra khi bạn sử dụng kết quả, không phải bên trong phương pháp này. Bạn có thể muốn thêm .ToList() vào cuối một số bước để nhận ra kết quả.

1

Cân nhắc việc sử dụng Code Contracts (ví dụ: thêm điều kiện sau vào ServerReport.GetParameters để đảm bảo rằng các phương thức không trả về bộ sưu tập trống). Họ cho phép làm những gì bạn muốn một cách thanh lịch hơn là viết logic kiểm tra của riêng bạn.

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]; 
    } 
} 

Cách sử dụng:

// Oops! I need at least one parameter! 
var parameters = new ServerReport().GetParameters(); 
+0

Điều đó nghe có vẻ lý tưởng. Tuy nhiên, trong trường hợp cụ thể của tôi, đó là dữ liệu cần tuân theo những kỳ vọng nhất định, vì vậy phân tích tĩnh không thể giúp được (tôi nhận ra điều này cũng cung cấp kiểm tra thời gian chạy, nhưng không chắc chắn sử dụng phương pháp mới này và sử dụng các công cụ mới được bảo hành trường hợp cho điều này). Tôi có thể tiêm logic của riêng mình khi một điều kiện không thỏa mãn không? Tôi thực sự cần phải nhìn sâu hơn vào điều này! – Clafou

+0

Tôi có nghĩa là logic sẽ cho phép tôi cung cấp một ngoại lệ hữu ích, cụ thể thay vì loại ngoại lệ chung, do đó làm cho mã gọi điện của tôi dễ dàng xử lý các lỗi có thể phục hồi. – Clafou

+0

@Clafou, vua bạn muốn tiêm loại logic nào? Vi phạm hợp đồng mang đến một 'ContractException'. Bạn có thể xử lý nó. – Dennis