2009-12-11 34 views
19

Tôi có một lớp ngoại lệ tùy chỉnh chứa một số trường bổ sung. Tôi muốn chúng được viết ra theo phương pháp ToString(), nhưng nếu tôi thực hiện ToString() của riêng mình, tôi mất một số thứ hữu ích khác (như viết tên kiểu ngoại lệ, dữ liệu ngoại lệ bên trong và dấu vết ngăn xếp).C#: Ghi đè phương thức ToString() cho các ngoại lệ tùy chỉnh

Cách/mẫu tốt nhất để triển khai phương pháp ToString() của riêng bạn cho các trường hợp ngoại lệ như vậy là gì? Lý tưởng nhất là nó nên tái sử dụng cơ chế hiện có, nhưng được định dạng theo cách tương tự như việc thực hiện ToString() mặc định.

UPDATE: thêm vào trước hoặc nối các lĩnh vực tùy chỉnh của tôi vào base.ToString() văn bản không phải là IMHO lý tưởng, ví dụ

PimTool.Utilities.OERestServiceUnavailableException: test ---> System.InvalidOperationException: inner message 
    --- End of inner exception stack trace --- 
    at PimTool.Tests.Services.OE.OERestClientTests.ExceptionsLogging() in D:\svn\NewPimTool\PimTool.Tests\Services\OE\OERestClientTests.cs:line 178, 
    StatusCode=0, message='test', requestId='535345' 

nghĩa các lĩnh vực tùy chỉnh được viết vào cuối của (có khả năng dài) mô tả ngoại lệ. Mặt khác, tôi muốn loại ngoại lệ là thông tin đầu tiên được ghi trong phần mô tả.

CẬP NHẬT 2: Tôi đã triển khai giải pháp cho vấn đề này, hãy tìm câu trả lời của riêng tôi bên dưới.

+0

Tôi đang tìm kiếm một điều tương tự, tôi muốn thêm một số thông tin bổ sung bên ngoài không trong trường Thông báo, nhưng tôi muốn định dạng ToString được giữ, với tất cả dấu vết ngăn xếp và ngoại lệ bên trong trên đó. Sẽ thú vị khi xem mã cho Exception.ToString() và sao chép nó thêm thông tin. – pauloya

+0

Vâng mã bao gồm hầu hết những điều bạn đã đề cập. Mặc dù sau đó tôi nhớ rằng tôi có thể đã sử dụng từ điển Exception.Data để lưu trữ các công cụ tùy chỉnh của mình. Tôi đoán trong trường hợp đó điều này sẽ được trả lại với việc thực hiện mặc định của ToString(), nhưng tôi đã không thử nó được nêu ra. –

Trả lời

10

OK, đây là những gì tôi đã đưa ra. Tôi đã thực hiện một lớp mở rộng mà tái tạo cơ chế gốc để định dạng ngoại lệ, nhưng với một twist: một đại biểu hành động tùy chỉnh trong đó cung cấp một plug-in để định dạng các lĩnh vực tùy chỉnh:

public static class ExceptionFormatterExtensions 
{ 
    public static string ExceptionToString (
     this Exception ex, 
     Action<StringBuilder> customFieldsFormatterAction) 
    { 
     StringBuilder description = new StringBuilder(); 
     description.AppendFormat("{0}: {1}", ex.GetType().Name, ex.Message); 

     if (customFieldsFormatterAction != null) 
      customFieldsFormatterAction(description); 

     if (ex.InnerException != null) 
     { 
      description.AppendFormat(" ---> {0}", ex.InnerException); 
      description.AppendFormat(
       "{0} --- End of inner exception stack trace ---{0}", 
       Environment.NewLine); 
     } 

     description.Append(ex.StackTrace); 

     return description.ToString(); 
    } 
} 

Bây giờ bạn có thể sử dụng phương pháp này trong triển khai ToString() của riêng bạn mà không cần sao chép mã định dạng:

public override string ToString() 
    { 
     return this.ExceptionToString(
      description => 
      { 
       description.AppendFormat(
        ", HttpStatusCode={0}, RequestId='{1}'", 
        httpStatusCode, 
        RequestId); 
      }); 
    } 
12

Bạn có thể thêm dữ liệu mặc định vào chuỗi được trả về bởi ToString theo cách thủ công bằng cách xem xét các thuộc tính ngoại lệ. Ví dụ, sau đây sẽ mô phỏng các dữ liệu trả về theo mặc định bằng phương pháp của một ngoại lệ ToString (giả sử không có trường hợp ngoại lệ bên trong):

string.Format("{0}: {1}\r\n{2}", this.GetType().Name, this.Message, this.StackTrace); 

Hoặc, bạn chỉ có thể thêm (hoặc thêm vào trước) dữ liệu trả về bởi base.ToString đến thông tin bạn muốn thêm.

+1

Điều này dường như là giải pháp gần gũi nhất với những gì tôi có trong đầu. Mặc dù bạn quên viết ra InnerException;) –

1

Bên trong base.ToString gọi override() và sửa đổi các chuỗi kết quả yêu cầu của bạn ...

10

Bạn có thể ghi đè lên các phương pháp ToString() để bao gồm thông tin tùy chỉnh của riêng bạn, và vẫn gọi ngoại lệ cơ sở mặc định ToString() như thế này:

public class MyException : Exception 
{ 
    public string CustomField { get; set; } 
    public override string ToString() 
    { 
     return CustomField + Environment.NewLine + base.ToString(); 
    } 
} 
4

Nếu bạn chủ yếu nhìn vào chúng trong trình gỡ lỗi, sau đó bạn có thể sử dụng thuộc tính [DebuggerDisplay] để xác định định dạng của họ và không chạm vào phương pháp hiện ToString.

Nếu không, chỉ quá tải ToString và chắc chắn để gọi phiên bản lớp cơ sở base.ToString()

+1

Mặc dù không phải những gì tôi đang tìm kiếm, +1 để đề cập đến nó. –

18

Đây là tất cả quá mức cần thiết. Ngoại lệ của bạn chỉ nên ghi đè Thuộc tính thư.

public override String Message { 
    get { 
     return base.Message + String.Format(", HttpStatusCode={0}, RequestId='{1}'", 
        httpStatusCode, 
        RequestId); 
    } 
} 

Phương thức ToString mặc định cho lớp Ngoại lệ về cơ bản là "ClassName: Message --> InnerException.ToString() StackTrace". Vì vậy, việc ghi đè Tin nhắn sẽ đặt văn bản tin nhắn của bạn chính xác vị trí của nó.

+0

Hoạt động trừ khi bạn đang đi xuống con đường này để tiêm dấu vết ngăn xếp tùy chỉnh. – yoyo

+0

@yoyo, vâng nhưng đó không phải là yêu cầu của OP – Daryl

+0

Hoàn toàn đúng và câu trả lời của bạn là một câu trả lời hay. (Tôi đến đây tìm kiếm một thứ gì đó hơi khác một chút.) – yoyo

Các vấn đề liên quan