Uniform handling of many exceptions

In my current project, I interact with some third-party middleware that generates many different types of exceptions (about 10 exceptions, etc.).

There are several methods in my library that uses a third party, each of which interacts with a third party, but it must be protected from the same set of 10 or more exceptions.

Currently, I have something like this in every method of my library:

try { // some code } catch (Exception1 e) { } catch (Exception2 e2) { } ... catch (ExceptionN eN) { } 

The number of exceptions may also increase.

How can I reduce code duplication and evenly process all exceptions in one place?

  • Suppose the processing in each method in my code is the same.
+4
source share
5 answers

You can use the global exception handler, the implementation depends on your type of project (ASP.net → global.asax, WPF → App.xaml ...)

Or use something like the following:

 private static void HandleExceptions(Action action) { try { action(); } catch (Exception1 e) { } catch (Exception2 e2) { } ... catch (ExceptionN eN) { } } 

which can be called as follows:

 HandleExceptions(() => Console.WriteLine("Hi there!")); 

If an exception was thrown during the execution of Console.WriteLine, then it will be processed by the exception handling logic

Note that executable code can also change external values:

 int x = 2; HandleExceptions(() => x = 2 * x); 

If you prefer anonymous methods:

 var x = 2; HandleExceptions(delegate() { x = x * 2; }); 
+3
source

I would start by catching the base type of Exception , and then filter it using the whitelist:

 try { // Code that might throw. } catch (Exception e) { if(e is Exception1 || e is Exception2 || e is ExceptionN) { // Common handling code here. } else throw; // Can't handle, rethrow. } 

Now, if you want to generalize the filter, you can write the extension:

 public static bool IsMyCustomException(this Exception e) { return e is Exception1 || e is Exception2 || e is ExceptionN; } 

and then you can just use:

 if(e.IsMyCustomException()) { // Common handling code here. } else throw; 

You can generalize the handler in a simple way:

 private void HandleCustomException(Exception e) { // Common handling code here. } 

If you want to generalize the entire try-catch block, you are probably best off attaching a delegate to a method that completes the operation, as mentioned in @vc 74.

+5
source

How to use one function to handle these Exceptions:

 try { //Some code here } catch(Exception e) { if(!ErrorHandler(e)) return null; //unhandled situation } private bool ErrorHandler(Exception e) { switch(e) { case Exception1: //Handle the exception type here return true; case Exception2: //Handle another exception type here return true; } return false; } 
+1
source

I recommend using the Enterprise Library 5.0 exception handling unit. Basically, you define several types of exceptions, categories, and exception handlers that handle specific types of exceptions. Ideally, you determine the type of exception, connect it to formatting, and then report the exception using the logging block.

You can read all about it here ...

+1
source

There are some semantic differences between catching and rebuilding an exception rather than catching it. Exceptional filters are therefore very useful, as they allow one, for example. "Catch Ex as an exception when IsNiceException (Ex)." Unfortunately, the only way to use them in a C # program is to use a DLL to wrap the necessary functionality (the DLL itself can be written in vb or in some other language). A typical template might be something like:

  TryWhenCatchFinally ( 
     () => {trycode;},
     (Exception ex) => {codeWhichReturnsTrueForExceptionsWorthCatching;},
     (Exception ex) => {codeToHandleException;},
     (ExceptionStatus status, Exception ex) => {finallyCode;});

The ExceptionStatus parameter for the "final" code will be an enumeration that states: (1) there was no exception, (2) an exception occurred, but was handled, (3) an exception occurred and was handled, but another exception was (4) an exception occurred, but CodeWhichReturnsTrueForExceptionsWorthCatching returns false; (5) an exception occurred that was not handled in trycode and not handled by this block, but trycode ended in any case (a rare situation, but there are ways in which this can happen). The Ex parameter is null in the first case and contains the corresponding exception in other cases - potentially useful information if an exception occurs when processing the finally block (suppressing the exception that occurs in the finally block may be bad, but if the exception has not been previously logged or is not lost before the exclusion of the new exception occurs, all data from the earlier exception will be completely lost; if the same condition that caused the earlier exception caused a later, earlier lawsuit The communication could have more useful information about what happened wrong).

By the way, a few notes with this template:

  1. Code that decides whether to catch an exception will be executed before nested finally blocks are executed; it can capture useful data for logging (the fact that, finally, the blocks were not started, can make it possible to write information that will be destroyed by the nested finally blocks), but the actual cleaning should usually be done after finally running blocks.
  2. Currently, it seems that exceptions that might get away from filters are suppressed, but I'm not sure if the behavior is guaranteed. Operations that may leak exceptions should probably not be performed in filters.
  3. If the "trycode" contains a try-finally block that is nested in a try-catch block, the exception that occurs in the "try" part of this try-finally block is not handled by TryCatchWhenFamily and no nested area, but it is handled by an external block, and the processing of the internal block try-finally throws an exception that handles the internal try-catch block; an exception that the external block decided to catch may disappear without even being caught. If the TryWhenCatchFinally method is encoded to detect this condition, it can report this finally code block (the finally block may or may not want to do anything with the condition, but it probably should at least be registered).
-1
source

Source: https://habr.com/ru/post/1386333/


All Articles