Click here to Skip to main content
15,888,096 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a question on how to properly adapt generic Action delegates to simple non-generic version of Action delegate.

I have a piece of code. I wish you could point to my errors or advise some other way to implement. I do have a doubt over capturing context of method arguments

C#
public static class TaskUtils
  {
      ///
      /// Executes ACTION delegate
      ///
      ///
      ///
      ///
      public static Task ExecuteAction(Action action, bool isAsync = true)
      {
          // validate action delegate
          Action execAction = Ensure.ArgumentNotNull(action, nameof(action), "Action delegate is not set (NULL)");

          if (!isAsync)
          {
              // do action execute
              try
              {
                  execAction();
                  return Task.CompletedTask;
              } catch (Exception ex)
              {
                  // failed handler
                  return Task.FromException(ex);
              }
          }

          // run a task in the system thread-pool
          return Task.Run(action, CancellationToken.None);
      }

      ///
      ///  Adapter function to fit ACTION delegte
      ///
      ///
      ///
      ///
      ///
      public static Action AdaptToRootAction(Action action, T arg)
      {
          // copy param
          T param = arg;

          return delegate
          {
              // pass parameter
              // and invoke ACTION
              action(param);
          };
      }

      public static Action AdaptToRootAction(Action action, T1 arg1, T2 arg2)
      {
          T1 param1 = arg1;
          T2 param2 = arg2;

          return delegate
          {
              // pass two generic parameters
              // and invoke ACTION delegate
              action(param1, param2);
          };
      }

      public static Action AdaptToRootAction(Action action, T1 arg1, T2 arg2, T3 arg3)
      {
          T1 param1 = arg1;
          T2 param2 = arg2;
          T3 param3 = arg3;

          return delegate
          {
              // pass three generic parameters
              // and invoke ACTION delegate
              action(param1, param2, param3);
          };
      }

      ///
      /// Executes a generic  with a passed value of type
      ///
      ///
      ///
      ///
      ///
      ///
      public static Task ExecuteAction(Action action, T arg, bool isAsync = true)
      {
          // adapt to root Action delegate and invoke
          Action rootAction = AdaptToRootAction(action, arg);
          return ExecuteAction(rootAction, isAsync);
      }


      public static Task ExecuteAction(Action action, T1 arg1, T2 arg2, bool isAsync = true)
      {
          // adapt to root Action delegate and invoke
          Action rootAction = AdaptToRootAction(action, arg1, arg2);
          return ExecuteAction(rootAction, isAsync);
      }
  }


What I have tried:

I tried to use my
C#
TaskUtils
class
Posted
Updated 5-Nov-17 18:48pm
Comments
Graeme_Grant 5-Nov-17 19:41pm    
I can see that you are in the middle of converting the class. My question is why do you want to remove the generic implementation? Generics help to reduce the amount of repetitive code, enforce types, and avoid the overhead of boxing.
NickResh777 5-Nov-17 22:51pm    
It's just to fit the constructor of the Task class cause it accepts only Action and Action<t> delegates

1 solution

I'll do one of your method calls for you... you need to tell the Action what to expect, just like the method wrapper:
C#
public static Action AdaptToRootAction<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
{
    T1 param1 = arg1;
    T2 param2 = arg2;

    return delegate
    {
        // pass two generic parameters
        // and invoke ACTION delegate
        action(param1, param2);
    };
}
 
Share this answer
 
Comments
BillWoodruff 7-Nov-17 7:03am    
That's very interesting code, but I admit to not seeing a reason to ever use such a technique. Yes, you can create a Delegate that wraps an Action with hard-coded parameters, and invoke it, but it will have no result, and will not modify anything ... because nothing's passed by reference. Of course you can't use 'ref or 'out with Action, or Func.

I think your advice to the OP to keep using generics is spot-on.

cheers, Bill (not voting on this).
Graeme_Grant 7-Nov-17 17:23pm    
Yes, agreed. I was not asking why, just taking care of the how... My original question still stands.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900