NickResh777 Ответов: 1

Адаптировать универсальные делегаты действий<T> к делегатам не-универсальных действий


У меня есть вопрос о том, как правильно адаптировать универсальные делегаты действий к простой не универсальной версии делегата действий.

У меня есть часть кода. Я хотел бы, чтобы вы могли указать на мои ошибки или посоветовать какой-то другой способ реализации. У меня есть сомнения по поводу захвата контекста аргументов метода

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);
      }
  }


Что я уже пробовал:

Я попытался использовать свой
TaskUtils
класс

Graeme_Grant

Я вижу, что вы находитесь в середине преобразования класса. Мой вопрос заключается в том, почему вы хотите удалить универсальную реализацию? Дженерики помогают уменьшить количество повторяющегося кода, принудительно применять типы и избежать накладных расходов на бокс.

NickResh777

Это просто для того, чтобы соответствовать конструктору класса Task, потому что он принимает только действие и делегаты Action<t>

1 Ответов

Рейтинг:
1

Graeme_Grant

Я сделаю один из ваших вызовов метода для вас... вам нужно сказать действию, чего ожидать, точно так же, как обертка метода:

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);
    };
}


BillWoodruff

Это очень интересный код, но я признаю, что не вижу причин когда-либо использовать такую технику. Да, вы можете создать делегат, который обертывает действие с жестко запрограммированными параметрами и вызывает его, но он не будет иметь никакого результата и ничего не изменит ... потому что ничто не передается по ссылке. Конечно, вы не можете использовать " ref " или "out with Action", или Func.

Я думаю, что ваш совет оператору продолжать использовать дженерики точен.

ваше здоровье, Билл (не голосуя по этому поводу).

Graeme_Grant

Да, согласен. Я не спрашивал почему, просто заботился о том, как... Мой первоначальный вопрос все еще остается в силе.