I have a particular situation where I need to trap exceptions and return an object to the client in place of the exception. I cannot put the exception handling logic at a higher level i.e. wrap Foo within a try clause.
It's best to demonstrate with some sample code. The exception handling logic is clouding the intention of the method and if I have, many methods of similar intent, in the Foo class, I find myself repeating most of the catch logic.
What would be the best technique to wrap the common exception functionality in the code below?
public class Foo
{
public Bar SomeMethodThatCanThrowExcepetion()
{
try
{
return new Bar().Execute();
}
catch(BazException ex)
{
WriteLogMessage(ex, Bar.ErrorCode);
return new Bar() { ErrorMessage = ex.Message, ErrorCode = Bar.ErrorCode;}
}
}
public Baz SomeMethodThatCanThrowExcepetion(SomeObject stuff)
{
try
{
return new Baz(stuff).Execute();
}
catch(BazException ex)
{
WriteLogMessage(ex, Baz.ErrorCode);
return new Baz() { ErrorMessage = ex.Message, ErrorCode = Baz.ErrorCode;}
}
}
}
"Don't repeat yourself" (DRY) is a principle of software development aimed at reducing repetition of software patterns, replacing it with abstractions or using data normalization to avoid redundancy.
DRY, which stands for 'don't repeat yourself,' is a principle of software development that aims at reducing the repetition of patterns and code duplication in favor of abstractions and avoiding redundancy.
If you can sense what type of exceptions may arise, create a small separate code to rebound from this state. Be specific about all different exceptions. Depending on your program, these exceptions may hamper your data if not written well. Try using statements that can make error handling for you.
DRY stands for Don't Repeat Yourself and the principle is that there should only ever be one copy of any important piece of information. The reason for this principle is that one copy is much easier to maintain than multiple copies; if the information needs to be changed, there is only one place to change it.
Updated per Lee's comment
One possibility is to use a generic helper method. Something like this:
T TryExecute<T>(Func<T> action, int ErrorCode)
{
try
{
return action();
}
catch (Exception ex)
{
result = Activator.CreateInstance<T>();
typeof(T).GetProperty("ErrorMessage").SetValue(result, ex.Message, null);
typeof(T).GetProperty("ErrorCode").SetValue(result, ErrorCode, null);
return result;
}
return result;
}
If you can modify Bar and Baz, then you could improve this by placing a requirement on T:
public interface IError
{
public string ErrorMessage { get; set; }
public int ErrorCode { get; set; }
}
T TryExecute<T>(Func<T> action, int ErrorCode) where T : IError
{
try
{
return action();
}
catch (Exception ex)
{
result = Activator.CreateInstance<T>();
result.ErrorMessage = ex.Message;
result.ErrorCode = ErrorCode;
return result;
}
}
Then you'd use:
return TryExecute<Bar>(new Bar().Execute, Bar.ErrorCode);
And:
return TryExecute<Baz>(new Baz(stuff).Execute, Baz.ErrorCode);
That may or may not be an over-abstraction for your particular design; the devil is in the details.
How about a base class:
public class ErrorCapable {
public string ErrorMessage { set; get; }
public int ErrorCode { set; get; }
public static ErrorCapable<T> Oops(Exception exc) where T : ErrorCapable, new() {
// Code for logging error here
return new T() { ErrorMessage = exc.Message, ErrorCode = exc.ErrorCode };
}
}
public class Bar : ErrorCapable {
//...
}
public class Baz : ErrorCapable {
//...
}
Then in the catch, just use, for example:
return ErrorCapable.Oops<Bar>(ex);
Do you really need the explicit logging in every method? Instead of having the exception logic in every method, have one handler in your Main
method of the program and handle the exceptions generically.
Also, you don't need to return an arbitrary object from a catch block should you really need the logging there, simply use throw;
to let it wander up the stack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With