CreateDelegate с использованием одного общего метода

#c# #.net #reflection

#c# #.net #отражение

Вопрос:

Я хочу создавать различные типы делегатов только с одним общим методом, подобным этому.

 public static object Boo(params object[] args) {
    return null;
}
  
 MethodInfo boo = /* MethodInfo of Boo */

// Boo's arg.Length should be `0`
Action action = (Action)Delegate.CreateDelegate(typeof(Action), null, boo);

Func<int> action2 = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), null, boo);
Func<string, string> action3 = (Func<string, string>)Delegate.CreateDelegate(typeof(Func<string, string>), null, boo);
  

Итак, если вы вызываете action3 так же, как это

 var ret = action3.Invoke("booo");
  

Значение Boo args.Length должно быть равно 1 и ret равно null .

Возможно ли это в C #?

  • Нет dynamic generic или linq.exprssion sry.

Обновить

Это должно быть сделано с Reflection помощью . Приведенные выше 3 делегата являются лишь примером. Тип делегатов будет определен во время выполнения.

Ответ №1:

Сначала вы можете определить делегат для вашего общего метода:

 public delegate object BooDelegate(params object[] args);
  

Вы можете использовать методы расширения следующим образом:

 public static class DelegatesProviderExtensions
{
    public static Func<int> GetFuncOfInt(this BooDelegate booDelegate) => () => (int) booDelegate();

    public static Action GetAction(this BooDelegate booDelegate) => () => booDelegate();

    public static Func<string, string> GetFuncOfStringString(this BooDelegate booDelegate) =>
        s => booDelegate(s) as string;
}
  

И тест:

 private static void Main(string[] args)
{
    BooDelegate boo1 = objects => 1;
    BooDelegate boo2 = objects =>
    {
        Console.WriteLine("Boo!");
        return null;
    };
    BooDelegate boo3 = objects => $"{objects[0]} World";

    Console.WriteLine(boo1.GetFuncOfInt()());
    boo2.GetAction()();
    Console.WriteLine(boo3.GetFuncOfStringString()("Hello"));
    Console.ReadLine();
}
  

Преимущество этого подхода заключается в том, что вы можете сделать свои методы расширения более полными и проверять ошибки, а Также давать отзывы и т. Д. И т. Д

Комментарии:

1. Блестяще! 🙂 🙂

Ответ №2:

Можете ли вы просто сделать:

 Action action = () => Boo();
Func<int> action2 = () => (int)Boo();
Func<string, string> action3 = x => (string)Boo(x);
  

Если нет, то почему бы и нет?

Ответ №3:

Наконец-то покончено с этим способом https://github.com/pjc0247/SlowSharp/blob/master/Slowsharp/Runner/Runner .Lambda.cs

Я думаю, что это не может быть сокращено без Linq.Выражение.