.NET/C# – ExceptionCatcher and ExceptionHelper gems
Posted by jpluimers on 2009/09/14
http://it-republik.de/dotnet/basta/The class presented in this article is part of my “.NET Gems – Small Pieces of Code that make your Day” session that will be presented at the BASTA! conference next week in Mainz, Germany.
It is going to be a fun conference, with lots of (internationally) renowned speakers (like Oliver Sturm, Ingo Rammer, Stephen Forte, Neil Ford and Dino Esposito).
Well worth attending!
OK. Let’s show the gems, and assume you are writing a method that is not allowed to let exceptions leave it’s implementation.
This is a common case, for instance you develop COM Servers, Windows Services and to a lesser extent Web Services.
All too often though, you forget to catch those exceptions and when one occurs (usually after the test cycle ends) you are screwed^H^H^H^H^H^H^H in trouble.
Or you start with a cleaner approach, where you indicate that something went wrong, and even return a meaningful string indicated what went wrong like this:
[WebMethod] public void WebServiceProcess(string argument, out bool succeeded, out string exceptionString) { try { // do something exceptionString = null; succeeded = true; } catch (Exception ex) { exceptionString = ex.ToString(); succeeded = false; } } [ComVisible(true)] public void ComServerProcess(string argument) { try { // do something } catch (Exception) { // eat all exceptions } }
(you can find more about the semantics of WebMethods returning multiple parameters in this “.Net WebServices and out/ref WebMethod arguments” stackoverflow thread)
Adding those blocks can be cumbersome, so I have written a few classes that can turn your code into this:
[WebMethod] public void WebServiceProcess(string argument, out bool succeeded, out string exceptionString) { ExceptionCatcher catcher = new ExceptionCatcher(); succeeded = catcher.Succeeded(out exceptionString, delegate { // do something } ); } [ComVisible(true)] public void ComServerProcess(string argument) { ExceptionHelper.Succeeded(delegate { // do something } ); }
Much more elegant code, with just a little effort, that also gives you Failed
and Catch
variants next to Succeeded
.
First the ExceptionHelper
, which defers all its work to ExceptionCatcher
:
using System; using System.Threading; namespace bo { public class ExceptionHelper { public static void Catch(SendOrPostCallback codeBlock) { ExceptionCatcher exceptionCatcher = new ExceptionCatcher(); exceptionCatcher.Catch(codeBlock); } public static bool Failed(SendOrPostCallback codeBlock) { ExceptionCatcher exceptionCatcher = new ExceptionCatcher(); bool result = exceptionCatcher.Failed(codeBlock); return result; } public static bool Succeeded(SendOrPostCallback codeBlock) { ExceptionCatcher exceptionCatcher = new ExceptionCatcher(); bool result = exceptionCatcher.Succeeded(codeBlock); return result; } } }
using System; using System.Threading; namespace bo { public class ExceptionCatcher { private Exception _Exception; public Exception Exception { get { return _Exception; } } private bool _Success; public bool Success { get { return _Success; } } public void Catch(SendOrPostCallback codeBlock) { _Exception = null; try { // need 1 argument, because it is a SendOrPostCallback codeBlock.DynamicInvoke(1); _Success = true; } catch (Exception ex) { #if DEBUG System.Diagnostics.Trace.WriteLine("ExceptionCatcher.Succeeded failure", ex.ToString()); #endif _Exception = ex; _Success = false; } } public bool Failed(SendOrPostCallback codeBlock) { bool result = !Succeeded(codeBlock); return result; } public bool Failed(out string exceptionString, SendOrPostCallback codeBlock) { bool result = !Succeeded(out exceptionString, codeBlock); return result; } public bool Succeeded(SendOrPostCallback codeBlock) { Catch(codeBlock); return _Success; } public bool Succeeded(out string exceptionString, SendOrPostCallback codeBlock) { bool result = Succeeded(codeBlock); if (result) exceptionString = this.Exception.ToString(); else exceptionString = string.Empty; return result; } } }
Hope these gems can make your code cleaner too!
–jeroen
Leave a Reply