This is a normal process in many apps, of course, but in many of these cases the catch and finally logic were duplicated. The more I worked with it, the more I felt like there had to be a way to create a re-usable function to handle it for me. What I came up with works pretty darn well, though it does make the code a little more complicated.
Code Snippet
- public static TResult TryCatch<TParam1, TResult, TException>(this Func<TParam1[], TResult> executeFunc, Func<TException, TResult> errorAction = null, Action<TParam1[]> finalAction = null, params TParam1[] args) where TException : Exception
- {
- if (executeFunc == null)
- throw new ArgumentNullException("executeFunc");
- try
- {
- return executeFunc.Invoke(args);
- }
- catch (TException ex)
- {
- if (errorAction != null)
- return errorAction.Invoke(ex);
- }
- finally
- {
- if (finalAction != null)
- finalAction.Invoke(args);
- }
- throw new ArgumentException("No return value specified");
- }
As you can see the function takes a variety of inputs to handle the guts of the code itself as well as the catch and finally blocks. The key parts of this function are:
- TParam1 - The type of parameter object
- TResult - The type of the return object
- TException - The type of exception expected to be caught
- executeFunc - The function to execute in the try block
- errorAction - An action to perform if an exception of the given type is caught
- finalAction - An action to perform on Finally
- args - An array of arguments passed to the executeFunc (if any)
Code Snippet
- [Test]
- public void TryCatch_Test()
- {
- var callback = false;
- Func<object[], bool> func = x =>
- {
- callback = true;
- return true;
- };
- Func<Exception, bool> showError = exception => false;
- var result = func.TryCatch(showError);
- Assert.That(result, Is.True);
- Assert.That(callback, Is.True);
- }
- [Test]
- public void TryCatch_Exception_Test()
- {
- var callback = false;
- Func<object[], bool> func = x => { throw new Exception("Test Exception"); };
- Func<Exception, bool> showError = exception =>
- {
- callback = true;
- return false;
- };
- var result = func.TryCatch(showError);
- Assert.That(result, Is.False);
- Assert.That(callback, Is.True);
- }
- [Test]
- public void TryCatch_DifferentType_Test()
- {
- var callback = false;
- var finalCallback = false;
- Func<int[], int> func = ints =>
- {
- callback = true;
- return ints.Sum();
- };
- Func<Exception, int> showError = exception => 0;
- Action<int[]> final = ints => { finalCallback = true; };
- var result = func.TryCatch(showError, final, 2, 5, 8);
- Assert.That(result, Is.EqualTo(15));
- Assert.That(callback, Is.True);
- Assert.That(finalCallback, Is.True);
- }
I included these three unit tests as I felt like they displayed the uses of this function quite nicely.
This code creates a nice re-usable function that gives us some real power and flexibility. No need to wrap your functions into a try-catch block. And since its an extension method you can write your Func and then tack the .TryCatch() call to the end.
No comments :
Post a Comment