Use func method for action?

I created an abstract function of the try / catch function. I have about 30 methods that have the same try / catch script. So I put it in one way:

private T Invoke<T>(Func<T> func) { try { return func.Invoke(); } catch (Exception ex) { throw LogAndThrowFaultException(ex); } } 

Now most methods call it this way:

  public IEnumerable<PingResponse> GetAllForPingRequest(PingRequest pingRequest) { return Invoke(() => PingResponseLogic.GetAllForPingRequest(pingRequest)); } 

My problem is that I have only a few methods that call it without having to return a value:

 Invoke<void>(() => CustomVariableGroupLogic.Delete(customVariableGroup)); 

However, I cannot use void there. The Invoke() method takes the value func , but in this case it must be action . I did some research, and it looks like I might have to create another Invoke() method, but take it to action. These proposals were made in 2009 and 2010. Is it possible to somehow use my func method without creating another Invoke() method, such as Invoke2() ?

+4
source share
4 answers

One quick and dirty solution would be to add a default value after calling the Delete method. In any case, it will be ignored unless you assign the result of the Invoke method to a variable. For example, the following code demonstrates this:

 Invoke(() => {CustomVariableGroupLogic.Delete(customVariableGroup); return 0; }); 

You can see a similar example suggested here ,

If you have many, many such calls, you can create a fancy shell that will return Func for this Action . Example:

 Func<Action, Func<int>> wrap = action => () => {action(); return 0;}; 

Now you can

 Invoke(() => wrap(() => CustomVariableGroupLogic.Delete(customVariableGroup))); 

but it's a little closer to lambda madness

Inspired by pcm2 :

you can create an overload for Invoke that simply takes Action as a parameter, use the solution above to invoke the implementation using Func<T> :

 public void Invoke(Action action) { Invoke(() => {action(); return 0;}); } 

now you just can

 Invoke(() => CustomVariableGroupLogic.Delete(customVariableGroup)); 
+5
source

Could you just create a call overload?

 public void Invoke<T>(Func<T> func){ return (T) InvokeInternal(func); } public void Invoke(Action action){ InvokeInternal(action); } 

If you want both methods to do the same and store DRY stuff, you could create a method like this:

 private object InvokeInternal(System.Delegate @delegate) { try { return @delegate.DynamicInvoke(); } catch (Exception ex) { throw LogAndThrowFaultException(ex); } } 

And you have your overloads calling this method, correspondingly giving the result, if any

+2
source
  • Do you really need func.Invoke() ? Why not just func() ?
  • Why is your Invoke static?
  • Depending on what LogAndThrowFaultException does, this can be very bad. Make sure the exception stack is maintained, always setting the internal exception in ex .

But yes, you need a second function that returns void instead of T.

+1
source

You can transfer the action to func like this. Or you can create a convenient function that performs a wrapper:

 void Main() { Action<string> a = s => Console.WriteLine(s); Invoke(() => { a(); return null; }); Invoke(s); } private void Invoke(Action a) { Invoke(() => { a(); return null; }; } 
+1
source

Source: https://habr.com/ru/post/1484495/


All Articles