The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,779 other followers

.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

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: