Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping calls to method on a class with a standard try/catch

Tags:

I have a class that has about 200+ methods, each of these methods makes a call into the database, or a network resource.

Ideally, I would like to wrap each call in a try/catch, to catch any of the common network or SQL exceptions, and give the user the opportunity to try again (if appropriate). However, to add this code to each call would be very time consuming, and bloated as far as the code is concerned.

I've thought about wrapping each of the method calls in another method, creating a delegate, and wrapping the delegate code in the try/catch.. something like this...

(Ignore the syntax.. it's just a conceptual example)

bool CallUpdatePassenger(int PassengerId,string PassengerName,string PhoneNumber) {     Delegate del= Delegate.CreateDelegate(typeof(UpdatePassengerDelegate), typeof(IPassengerServices).GetMethod("RemoteUpdatePassenger"));     bool Res=(bool)CallDelegate(del,PassengerName,PhoneNumber); } object CallDelegate(Delegate del,params object[] args) {     object Result=null;     try     {         Result=del.DynamicInvoke(args);     }     catch (Some.Timeout.Error.Or.Whatever te)     {         // take some action.. maybe retry etc..      }     return Result; } 

Maybe there's a more pracitcal way of doing this ?

The code is automatically generated (by a tool which I wrote) I can quite easily include something like the above, but I want to avoid writing the above code for every method call.

Also, if I do something like the above, I can time methods, and log method calls etc. It just seems a bit clumsy (and not strongly typed).

Thanks Rich.

like image 576
Rich S Avatar asked Dec 23 '11 15:12

Rich S


People also ask

Should you wrap everything try catch?

Exactly. Putting everything in a try/catch statement is usually a sign of an inexperienced developer who doesn't know much about exceptions IME.

Should every method have try catch?

Don't try to catch specific exceptions that are due to bugs - you want them to fail, get logged, then get fixed. And no, you definitely don't want to wrap every method call with a try/catch block. "So they can trace where exceptions occur" - that's what the stack trace is for...

What code is intended to be wrapped in a try block?

The code that we imagine might be problematic, the call to Connect(), is now wrapped in a try block. Any exception that occurs in the code inside the catch block will immediately transfer to the code in the catch block, where we can specify what we want to happen if the call fails.

Is it bad practice to use try catch?

Without a try catch, you run the risk of encountering unhandled exceptions. Try catch statements aren't free in that they come with performance overhead. Like any language feature, try catches can be overused.


2 Answers

You should be able to just do something like:

T Execute<T>(Func<T> func) {     try {         return func();     } catch (...) {         ...     } } bool CallUpdatePassenger(some args here) {     return Execute( () => realObj.RemoteUpdatePassenger(some args here)); } 

alternatively, you could use meta-programming to write a dynamic "decorator" for the underlying methods on the fly... but unless you are familiar with ILGenerator etc probably best not to - it is a fairly advanced topic.

like image 171
Marc Gravell Avatar answered Oct 06 '22 00:10

Marc Gravell


I think your basic idea is good, but there's a simpler way to implement it (at least of you're using .Net 3.5 or more recent):

void WithStandardRetryLogic(Action method)  {     try     {         method();     }     catch (Some.Timeout.Error.Or.Whatever te)          {                  // take some action.. maybe retry etc..           }  } 

Example use:

WithStandardRetryLogic(delegate() { CallUpdatePassenger(PassengerId, PassengerName, PhoneNumber); }); 

This may also be something where an AOP framework might be useful, but I have not tried that solution.

like image 24
ckarras Avatar answered Oct 05 '22 23:10

ckarras