14

Tôi hiện đang phát triển một giải pháp và đã thiết kế giải pháp theo cách sao cho nó thực hiện mạnh mẽ mẫu chiến lược/nhà cung cấp. Như vậy giải pháp cho thấy một số giao diện và chứa các triển khai mặc định của các giao diện này có thể được thay thế thông qua phương pháp loại DI.Làm cách nào để chỉ định ngoại lệ được trình tạo bởi một người triển khai giao diện?

Trường hợp ứng dụng máy chủ sử dụng một số các giao diện nó là hy vọng để xử lý một số trường hợp ngoại lệ có thể xảy ra, cho giao diện ví dụ IDataRetriever có một phương pháp SomeDataType GetData(int timeout); và máy chủ có thể xử lý một số trường hợp ngoại lệ tùy chỉnh như DataRetrievalTimeoutException hoặc NetworkConnectionException.

Câu hỏi của tôi là cách tốt nhất để đánh dấu lớp giao diện như thế nào khi một nhà phát triển triển khai nó, họ sẽ biết rằng một số ngoại lệ nhất định phải được ném và sẽ được xử lý bởi máy chủ?

Hiện tại tôi vừa thêm thẻ xml ngoại lệ vào các phương thức nhận xét xml - điều này có đủ không?

Trả lời

12

Thẻ XML (và bất kỳ tài liệu nào khác bạn muốn viết) về cơ bản là gần nhất bạn có trong "vanilla" .NET vào lúc này.

Bạn có thể muốn nhìn vào Code Contracts cho phép bạn chú thích giao diện của bạn với các hợp đồng, trong đó có thể bao gồm trường hợp ngoại lệ, điều kiện tiên quyết, vv

+0

Lưu ý rằng liên kết sẽ trỏ đến https://github.com/Microsoft/CodeContracts – Josh

+0

@Josh: Đã cập nhật, cảm ơn. –

0

Tôi nghĩ rằng cách tốt nhất để cung cấp thông tin này là trong tài liệu XML mà bạn sẽ cung cấp cho mỗi giao diện. Ở đó bạn có thể chỉ định Exception được ném bởi phương thức nào để host có thể xử lý lỗi đó.

2

Bạn không thể trong giao diện. Bạn CÓ THỂ trong một lớp cơ sở.

public interface IFoo 
{  
    /// <summary> 
    /// Lol 
    /// </summary> 
    /// <exception cref="FubarException">Thrown when <paramref name="lol"> 
    /// is <c>null</c></exception> 
    /// <remarks>Implementors, pretty please throw FE on lol 
    /// being null kthx</remarks> 
    void Bar(object lol); 
} 

vs

public abstract BaseFoo 
{  
    /// <summary> 
    /// Lol 
    /// </summary> 
    /// <exception cref="FubarException">Thrown when <paramref name="lol"> 
    /// is <c>null</c></exception> 
    public void Bar(object lol) 
    { 
    if(lol == null) 
     throw new FubarException(); 
    InnerBar(lol); 
    } 

    /// <summary> 
    /// Handles execution of <see cref="Bar" />. 
    /// </summary> 
    /// <remarks><paramref name="lol"> is guaranteed non-<c>null</c>.</remarks> 
    protected abstract void InnerBar(object lol); 
} 
+1

Nếu bạn muốn đảm bảo rằng 'Bar' không rò rỉ bất kỳ loại ngoại lệ bất ngờ nào, tôi nghĩ rằng phương thức' Bar' không ảo cần bọc lệnh gọi 'InnerBar' trong khối try-catch, nó sẽ bắt và bọc bất kỳ ngoại lệ nào ngoại trừ những ngoại lệ được chỉ định trong giao diện. – supercat

0

Một chiến lược nếu bạn không thể hỗ trợ một lớp cơ sở chung, là phương pháp khuyến nông triển khai.

public static void ThisMethodShouldThrow(this Iinterface obj) 
{ 
    if(obj.ConditionToThrowIsMet) throw new... 
} 

Điều này có lợi cho phép bạn không yêu cầu chuỗi kế thừa.

0

Điều này có xảy ra với bất kỳ lớp nào thực hiện Giao diện không?

Ví dụ: nếu tôi lấy Giao diện và triển khai lớp học của riêng mình, với phương thức GetData, tôi có thể là 'đang' lấy dữ liệu từ bất kỳ đâu. Cho phép nói rằng đó là một dịch vụ web sau đó các loại ngoại lệ có thể được ném có thể khác với những người nếu tôi đã 'nhận' dữ liệu từ hệ thống tập tin địa phương. Vì vậy, trong thực hiện của tôi, tôi sẽ thực hiện (và tài liệu) những ngoại lệ cụ thể cho implmentation để bất kỳ mã nào đang sử dụng triển khai có thể xử lý chúng. Làm thế nào những ngoại lệ được xử lý có thể rất cụ thể để thực hiện, nói rằng tôi đang tiêu thụ chúng trong một ứng dụng web như trái ngược với một ứng dụng máy tính để bàn.

+1

Mục đích của giao diện là cho phép các triển khai khác nhau có thể hoán đổi cho nhau. Nếu việc thực thi 'IEnumerable/IEnumerator' đọc dữ liệu từ 'AcmeDatabase' là cho phép một số loại' AcmeDatabaseException' thoát, người gọi sẽ không biết cách nào có thể biểu diễn một giao tiếp tạm thời hay không. CPU đang cháy. Hợp đồng 'IEnumerable' không cung cấp bất kỳ hướng dẫn hữu ích, than ôi, nhưng đó không phải là lý do giao diện khác không nên làm tốt hơn, ví dụ: xác định rằng ... – supercat

+1

... bất kỳ nỗ lực nào để thực hiện 'IWoozle.wozzle' mà không thể hoàn thành nhưng rời khỏi trạng thái hệ thống không thay đổi gì sẽ ném' IWoozle.CleanFailureException' hoặc một dẫn xuất của nó. Nếu trạng thái của 'IWoozle' có thể đã thay đổi nhưng, từ quan điểm' IWoozle' có khả năng hợp lệ, 'IWoozle.PossibleChangeException'. Nếu trạng thái của 'IWoozle' có khả năng bị hỏng, nhưng tham nhũng bị giới hạn đối tượng đó,' IWoozle.CorruptObjectedException'. Không cho phép bất kỳ ngoại lệ nào khác ngoài trường hợp trên để thoát trừ khi CPU đang cháy hoặc tình trạng quyết liệt khác tồn tại. – supercat

+0

Ok, tôi hiểu câu nói của bạn. Vì vậy, về cơ bản nếu tôi lấy giao diện Gouldos và triển khai GetData, đằng sau hậu trường tôi đã mã hóa để truy xuất dữ liệu qua dịch vụ web và một số ngoại lệ cụ thể dịch vụ web xảy ra :-), thì tôi sẽ phải loại bỏ ngoại lệ này và chuyển bất kỳ chi tiết nào trở lại thông qua việc tăng nói NetworkConnectionException? Và người gọi sau đó sẽ dựa vào việc lấy thông tin về ngoại lệ cơ bản thông qua thuộc tính ngoại lệ bên trong .... một cái gì đó như thế? – SleepyBoBos

2

Tôi khuyên bạn nên xác định các lớp ngoại lệ trong giao diện và xác định rằng không có ngoại lệ nào không xuất phát từ những trường hợp được phép thoát trừ khi CPU đang cháy hoặc tình trạng quyết liệt khác tồn tại (thậm chí sau đó, nó có thể không được một ý tưởng tồi để có một cách rõ ràng định nghĩa IWoozle.SystemCorruptionException để nếu một trình xử lý Pokemon chỉ đơn giản là bắt, ghi và ném ra ngoại lệ, nhật ký sẽ phản ánh rằng ít nhất ai đó nghĩ rằng ngoại lệ là quan trọng).

tôi xem xét đề nghị của Microsoft để tránh việc xác định loại ngoại lệ tùy chỉnh là bất hạnh, vì nó có nghĩa là không có cách nào sạch để phân biệt cho dù IEnumerator<T>.MoveNext() ném một InvalidOperationException vì bộ sưu tập cơ bản đã được thay đổi trong quá trình điều tra, hay quá trình xử lý nội bộ của IEnumerator<T>.MoveNext() cuộc gặp gỡ một số InvalidOperationException và chỉ đơn giản cho phép nó bong bóng đến người gọi. Nếu thay vào đó, IEnumerator<T>.MoveNext() đã ném IEnumerator.InvalidatedEnumeratorException vào trường hợp trước đó, thì bất kỳ InvalidOperationException nào đã thoát sẽ phải đại diện cho trường hợp sau.

+2

+1 cho trình xử lý Pokemon. Tiếng cười hay nhất trong ngày. –

+0

Điều này nghe có vẻ như những gì OP đang tìm kiếm, tuy nhiên bạn không nói * làm thế nào * để làm điều đó. – Josh