I created a method to abstract try/catch functionality. I have about 30 methods that have this exact same try/catch scenario. So I put it in one method:
private T Invoke<T>(Func<T> func)
{
try
{
return func.Invoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
Now, most of the methods call it like this:
public IEnumerable<PingResponse> GetAllForPingRequest(PingRequest pingRequest)
{
return Invoke(() => PingResponseLogic.GetAllForPingRequest(pingRequest));
}
My issue is that I have just a couple of methods that call it without needing to return a value:
Invoke<void>(() => CustomVariableGroupLogic.Delete(customVariableGroup));
However, I can't use void
there. The Invoke()
method takes a func
, but in this case it needs to be an action
. I did some research and it looks like I may have to create another Invoke()
method, but have it take an action. Those suggestions were from 2009 and 2010 though. Is it possible to somehow use my func method without having to create another Invoke()
method like Invoke2()
?
One quick and dirty solution would be to add default value after calling Delete
method. It will be ignored anyway, if you don't assign result of the Invoke
method to a variable. For instance, next code demonstrates this:
Invoke(() => {CustomVariableGroupLogic.Delete(customVariableGroup); return 0; });
You can see similar example proposed here,
If you have lots and lots of such calls, you can build a fancy wrapper, that will return Func
for a given Action
. Example:
Func<Action, Func<int>> wrap = action => () => {action(); return 0;};
now you can
Invoke(() => wrap(() => CustomVariableGroupLogic.Delete(customVariableGroup)));
but this goes a little bit close to lambda craziness
Inspired by pcm2:
you can create an overload to Invoke
, that simply takes Action
as a parameter, use solution proposed above to call implementation with Func<T>
:
public void Invoke(Action action)
{
Invoke(() => {action(); return 0;});
}
now you simply can
Invoke(() => CustomVariableGroupLogic.Delete(customVariableGroup));
Could you not just create an overload of invoke?
public void Invoke<T>(Func<T> func){
return (T) InvokeInternal(func);
}
public void Invoke(Action action){
InvokeInternal(action);
}
If you'd then want both methods to do the exact same thing, and keeping things DRY, you could create a method like so:
private object InvokeInternal(System.Delegate @delegate)
{
try
{
return @delegate.DynamicInvoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
And have both your overloads calling this method, appropriately casting the result, if any
func.Invoke()
? Why not just func()
?Invoke
static?LogAndThrowFaultException
is doing, this could be pretty bad. Make sure that the exception stack is preserved by always setting the inner exception to ex
.But yes, you need a second function that returns void instead of T.
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