2009-08-03 39 views
17

Tôi có một lớp với số phương thức và muốn có một trình xử lý ngoại lệ cho tất cả chúng. Có rất nhiều các phương pháp này và chúng có các tham số khác nhau, rằng nó sẽ là xấu xí để viết try/catch cho mỗi người trong số họ.Một trình xử lý ngoại lệ cho tất cả các ngoại lệ của CLASS

Bạn có thể biết cách tôi có thể làm điều đó với việc có một bộ xử lý ngoại lệ trong lớp, điều này sẽ xử lý tất cả.

UPDATE:


Nhiều bạn hỏi tôi tại sao. Lý do là tôi đang gọi một nguồn dữ liệu với các phương thức khác nhau. vì vậy lớp của tôi có hàm getData1, gedData2, getData3, getData4, ...., getDataN. Vấn đề là không có cách nào để kiểm tra xem kết nối vẫn còn mở và tạo kết nối mới là rất rất tốn kém. Vì vậy, tôi đang cố gắng tái sử dụng kết nối và nếu kết nối trên cuộc gọi tiếp theo đã thất bại, tôi sẽ bắt và kết nối lại và thử lại. Đó là lý do tại sao tôi cần điều này thử/bắt tất cả các khối.

để làm điều này cho tất cả các chức năng:

try{  
    datasource.getData() 
} 
catch(ConnectionException) 
{ 
    datasource.Connect(); 
    datasource.getData() 
} 

Cảm ơn

+0

Tôi biết đó là một câu hỏi cũ nhưng tôi muốn nói rằng mặc dù tôi chủ yếu là đồng ý với trả lời dưới đây đã được gửi vào ngày câu hỏi được hỏi, có những lúc khả năng này sẽ rất hữu ích. husayt mô tả một ở trên và tôi tìm thấy câu hỏi này bởi vì tôi có một kịch bản khác. Mặc dù câu trả lời của Jack Allan không hoạt động cho kịch bản của tôi, tôi đã bình chọn nó vì nó rất hữu ích trong các tình huống khác và nó rất thông minh, IMHO. Điều đó nói rằng, trước khi bạn sử dụng "giải pháp" của Jack, hãy chắc chắn rằng không có cách nào khác để cấu trúc mã của bạn để tránh sự cần thiết cho điều này hoàn toàn. –

+0

Không có cơ chế như vậy - cũng không nên có, IMHO. Nó không nhất quán với cách thức luồng điều khiển được truyền đi xung quanh. Việc bạn phải làm là "xấu xí" không quan trọng. Nó không quan trọng là giải pháp bạn đã làm, đòi hỏi phải viết thêm mã. Điều quan trọng là bạn có thể viết phần mềm dễ hiểu, và để duy trì sau này, khi bạn (hoặc người khác) đã quên các chi tiết ban đầu. Nếu một phương thức cần phải làm điều gì đó khi một ngoại lệ xảy ra, thì PHẢI có cái gì đó trong phương pháp, điều đó nói phải làm gì. Đây là một điều tốt. – ToolmakerSteve

+0

BTW, tôi đã upvoted câu hỏi, bởi vì tôi nghĩ rằng đây là một câu hỏi tuyệt vời. Nó là hợp pháp, và hữu ích cho người khác, để MUỐN làm điều này. Hiểu TẠI SAO không có cách nào để làm điều này, và hiểu những gì nên làm (mà bạn đã làm, trong câu hỏi của bạn, mặc dù bạn không thích kết quả), sẽ hữu ích cho người khác. – ToolmakerSteve

Trả lời

19

Bạn có thể sử dụng một đại biểu để vượt qua mã của phương pháp của bạn thành một catch duy nhất như ví dụ sau:

private void GlobalTryCatch(Action action) 
    { 
     try 
     { 
      action.Invoke(); 
     } 
     catch (ExpectedException1 e) 
     { 
      throw MyCustomException("Something bad happened", e); 
     } 
     catch (ExpectedException2 e) 
     { 
      throw MyCustomException("Something really bad happened", e); 
     } 
    } 

    public void DoSomething() 
    { 
     GlobalTryCatch(() => 
     { 
      // Method code goes here 
     }); 
    } 
1

Tôi không nghĩ rằng có. Bạn có thể di chuyển try/catch cho người gọi, nhưng đó không phải là thiết kế rất tốt. Nó có thể tốt hơn để tách nó ra thành một lớp khác, và sử dụng Reflection để gọi các phương pháp, như thế này:

public class MyClass {} 
public class MySafeClass { 
    public void CallMethod(string name, object[] param) { 
     Type t = typeof(MyClass); 
     MyClass mc = new MyClass(); 
     try { 
      t.GetMethod(name).Invoke(mc, param); 
     } 
     catch { 
      //...; 
     } 
    } 

}

Nhưng bạn không nên! Nó không phải là thực hành rất tốt.

phương pháp khác là vẫn còn sử dụng try/catch nhưng có một phương pháp duy nhất để ném ngoại lệ, vv lại cho người sử dụng:

public class MyClass { 
    void DoException(string message) { 
     throw new Exception(message); 
    } 
} 

Nhưng mà vẫn không phải là tốt một lựa chọn.

Tôi không thấy lý do tại sao nó sẽ xấu - ngay cả khi bạn chỉ quấn toàn bộ phương thức trong một lần thử/bắt với một thông điệp. Điều đó có thể khả thi.

Nó cũng là một lựa chọn tốt hơn để chỉ để lại cho họ và chuyển chúng trở lại cho người gọi, có lẽ trong try/finally.

Thật khó để thử/nắm bắt mọi thứ, đặc biệt là với các đoạn mã trong Visual Studio và SharpDevelop.

+0

Cảm ơn bạn đã trả lời. Có thể nhìn vào bản cập nhật cho câu hỏi bạn có thể thấy lý do của tôi. – husayt

1

Điều này nghe có vẻ giống như một vấn đề với thiết kế của bạn. Bạn có thể xây dựng chính xác về những ngoại lệ bạn đang cố gắng nắm bắt và lý do tại sao chúng tôi có thể thử và trợ giúp điều đó không.

+0

có thể tôi cần cung cấp thêm ngữ cảnh, hãy kiểm tra cập nhật của tôi cho câu hỏi. – husayt

1

Trường hợp ngoại lệ không thực sự liên quan đến lớp học nhưng phương pháp/callstack được định hướng. Một đối tượng nên, nói chung, không cố gắng xử lý các ngoại lệ từ các phương thức riêng của nó. Nó tùy thuộc vào người gọi những phương pháp đó.

0

bạn có thể muốn đặt thử/nắm bắt về phương pháp chính, mặc dù tôi coi đây là hành vi lạm dụng ngoại lệ nghiêm trọng, ngoại trừ bạn muốn nối thêm trình ghi nhật ký hoặc sth.

+0

tôi chỉ cần một cái gì đó cho lớp đó và được xử lý bên trong lớp đó Thnks – husayt

12

tôi không thể tìm ra bất cứ lý do tại sao bạn có thể được hưởng lợi từ việc xử lý tất cả các trường hợp ngoại lệ trong một lớp học sử dụng một phương pháp duy nhất (bạn có thể xây dựng? Tôi tò mò ...)

Dù sao, bạn có thể sử dụng AOP (Kỹ thuật lập trình hướng khía cạnh) các kỹ thuật để tiêm (tĩnh hoặc lúc chạy) mã xử lý ngoại lệ xung quanh các phương thức của lớp của bạn.

Có một thư viện lắp ráp tốt sau xử lý được gọi là PostSharp mà bạn có thể cấu hình sử dụng các thuộc tính về các phương pháp trong lớp học của bạn:

Bạn có thể xác định một khía cạnh như thế này (từ trang web PostSharp):

public class ExceptionDialogAttribute : OnExceptionAspect 
{ 
    public override void OnException(MethodExecutionEventArgs eventArgs) 
    { 
     string message = eventArgs.Exception.Message; 
     MessageBox.Show(message, "Exception"); 
     eventArgs.FlowBehavior = FlowBehavior.Continue; 
    } 
} 

Và sau đó bạn sẽ áp dụng thuộc tính cho các phương pháp bạn muốn xem ngoại lệ, như thế này:

public class YourClass { 

    // ... 

    [ExceptionDialog] 
    public string DoSomething(int param) { 
     // ... 
    } 
} 

Bạn cũng có thể áp dụng thuộc tính cho toàn bộ lớp học, như sau:

[ExceptionDialog] 
public class YourClass { 
    // ... 
    public string DoSomething(int param) { 
     // ... 
    } 
    public string DoSomethingElse(int param) { 
     // ... 
    } 
} 

Điều này sẽ áp dụng lời khuyên (mã xử lý ngoại lệ) cho mọi phương thức trong lớp học.

+1

Câu trả lời hay. Chỉ cần FYI, có vẻ như PostSharp đã thay đổi chữ ký OnException thành OnException (MethodExecutionArgs eventArgs) cho phương thức ảo. – joshmcode

+0

Tôi chỉ muốn thêm trường hợp sử dụng của tôi cho điều này, tôi đang tạo một mod cho một trò chơi. Trong trường hợp một ngoại lệ được ném mà tôi đã không bắt, tôi muốn mod của tôi để de-đăng ký chính nó và đăng nhập các lỗi (thay vì sụp đổ các trò chơi). Vì vậy, điều này là thuận tiện. –