Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WinForms, .Net Framework Новый топик    Ответить
 MulticastDelegate и Task  [new]
Antonariy
Member

Откуда: ☭
Сообщений: 72998
Есть некий супер-пупер метод, фишку которого можно свести к этим строкам:

public static object ReturnCall<T>(T func, object[] values) where T : MulticastDelegate
    => func.Method.Invoke(func.Target, values);

//вызов: 
var xyz = ReturnCall<Func<int, string, long>>(SomeFunc, values)

//что вызывается:
long SomeFunc(int x, string y) {}
        

Не спрашивайте, почему такой непрямой вызов - религия позволяет только так.

А как сделать await всей этой пирожни, если вызывается async?
var xyz = ReturnCall<Func<int, string, Task<long>>>(SomeFunc, values)

async Task<long> SomeFunc(int x, string y) {}
25 окт 21, 22:29    [22388074]     Ответить | Цитировать Сообщить модератору
 Re: MulticastDelegate и Task  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6257
Как-то вот так:
public class Program
{
  static async Task Main()
  {
    var result = (int)await ReturnCallAsync<Func<string, Task<int>>>(Foo, new object[]{"0123456789"});
    Console.WriteLine(result);
    await CallAsync<Func<IEnumerable<string>, Task>>(Bar, new object[]{new[] {"foo", "bar", "zot"}});
  }

  static async Task<object> ReturnCallAsync<T>(T func, object[] values) where T : MulticastDelegate
  {
    var returnType = func.Method.ReturnType;
    if (!(typeof(Task).IsAssignableFrom(returnType) && returnType.IsGenericType))
      throw new InvalidOperationException();
    dynamic awaiter = func.Method.Invoke(func.Target, values);
    await awaiter;
    return awaiter.GetAwaiter().GetResult();
  }

  static async Task CallAsync<T>(T action, object[] values) where T : MulticastDelegate
  {
    var returnType = action.Method.ReturnType;
    if (!(typeof(Task).IsAssignableFrom(returnType) && !returnType.IsGenericType))
      throw new InvalidOperationException();
    dynamic awaiter = action.Method.Invoke(action.Target, values);
    await awaiter;
  }

  static async Task<int> Foo(string argument)
  {
    await Task.Yield();
    return argument?.Length ?? -1;
  }

  static async Task Bar(IEnumerable<string> arguments)
  {
    await Task.Yield();
    Console.WriteLine(arguments?.Any() ?? false ? arguments.Aggregate((a,b)=>$"{a},{b}") : "sequence is empty");
  }
}

Если использование dynamic не устраивает - результат Invoke приводить к Task (Task<TResult> унаследован от просто Task), ему делать await, и если делегат возвращает Task<TResult>, то рефлекшеном получать значение Task<TResult>>.Result.
26 окт 21, 07:29    [22388143]     Ответить | Цитировать Сообщить модератору
 Re: MulticastDelegate и Task  [new]
Antonariy
Member

Откуда: ☭
Сообщений: 72998
Спасибо!
26 окт 21, 12:18    [22388272]     Ответить | Цитировать Сообщить модератору
 Re: MulticastDelegate и Task  [new]
hVostt
Member

Откуда:
Сообщений: 19352
Antonariy,

шож вы там такое делаете, стесняюсь спросить )
29 окт 21, 04:46    [22389705]     Ответить | Цитировать Сообщить модератору
 Re: MulticastDelegate и Task  [new]
Ролг Хупин
Member

Откуда: Чебаркуль
Сообщений: 4450
hVostt
Antonariy,

шож вы там такое делаете, стесняюсь спросить )


пусть делает, не трогайте его (ц)
29 окт 21, 08:40    [22389726]     Ответить | Цитировать Сообщить модератору
Все форумы / WinForms, .Net Framework Ответить