учитывая метод, который принимает метод в качестве входных данных, получить его класс и имя метода - PullRequest
0 голосов
/ 25 июня 2019

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

У меня есть класс Form1.cs, в котором я создал этот метод:

public static void CalculateTime(Action<string> funcToCalc, string where)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();

            funcToCalc(where);

            watch.Stop();
            var elapsedMs = watch.ElapsedMilliseconds;
            // gets the textbox name
            TextBox t = Application.OpenForms["Form1"].Controls["textBox1"] as TextBox;
            // writes in the textbox of this form this string
            t.AppendText(funcToCalc.Method.Name + " executed in " + elapsedMs + "ms;\n");

        }

В этом классе я вызываю этот метод следующим образом:

CalculateTime( Class1.CreateStuff, textPath.Text);
CalculateTime( Class2.CreateStuff, textPath.Text);

Что я хочу сделать, это распечатать что-то вроде

"MyClass1.CreateStuff executed in 100ms"
"MyClass2.CreateStuff executed in 75ms"

и т.д.

Пока мой метод печатает

"CreateStuff executed in 100ms"
"CreateStuff executed in 75ms"

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

Есть ли способ получить имя класса в данном конкретном случае?

Обратите внимание, что если в моем CalculateTime я звоню

System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name;

Я получаю строку "Form1".

Ответы [ 2 ]

4 голосов
/ 25 июня 2019

Самый простой способ - запросить свойство делегата Method, которое указывает на выполняемый метод.

Обратите внимание, что, хотя оно работает для статических членов и членов экземпляра, оно не 'Обязательно имеет смысл при вызове анонимного делегата (когда возвращается бессмысленное имя метода, созданного компилятором):

using System;

public class Foo1
{
  // static
  public static void Method( string s )
  {
  } 
}
public class Foo2
{
  // instance
  public void Method( string s )
  {
  }
}

public class Program
{
  public static void  Main(string[] args)
  {
    PrintDelegateInfo( Foo1.Method );
    PrintDelegateInfo( new Foo2().Method );
    PrintDelegateInfo( (Action<string>)(s => {}) );
  }

  private static void PrintDelegateInfo(Action<string> funcToCall)
  {
    var methodInfo = funcToCall.Method;
    var name = string.Format( "{0}.{1}", methodInfo.DeclaringType.Name, methodInfo.Name );

    Console.WriteLine( "{0} called", name );
  }
}

Вывод:

Foo1.Method called
Foo2.Method called
Program.<Main>b__0 called
3 голосов
/ 25 июня 2019

Вы можете использовать в самом действии метод расширения GetMethodInfo (Delegate) для того, чтобы MethodInfo для делегата. Предполагая, что вы не передаете анонимный типизированный делегат, такой как функция Lambda, вы можете использовать это MethodInfo, чтобы получить тип класса, используя DeclaringType, например:

public static void CalculateTime(Action<string> funcToCalc, string where)
    {   
        var miAction = funcToCalc.GetMethodInfo();
        var actionContainingType = miAction.DeclaringType;
        var watch = System.Diagnostics.Stopwatch.StartNew();

        funcToCalc(where);

        watch.Stop();
        var elapsedMs = watch.ElapsedMilliseconds;
        // gets the textbox name
        TextBox t = Application.OpenForms["Form1"].Controls["textBox1"] as TextBox;
        // writes in the textbox of this form this string
        t.AppendText($"{actionContainingType.Name}.{funcToCalc.Method.Name} executed in {elapsedMs} ms;\n");

    }
...