Don Diego
Don Diego

Reputation: 1488

given a method that takes a method as input, get its class and method name

I was wondering if it is possible to get method and class name of an inputted function of a method. I'll try to be more specific:

I have a class Form1.cs in which i created this method:

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

        }

In this class I call this method in this way:

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

What I want to do is to print out something like

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

etc.

For now, my method prints out

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

which does not allow me to recognize the class of the method called.

Is there a way to get the class name in this particular case?

Note that if in my CalculateTime i call

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

I get the string "Form1".

Upvotes: 1

Views: 119

Answers (2)

Mischa Vreeburg
Mischa Vreeburg

Reputation: 1586

You can use on the action itself the extention method GetMethodInfo(Delegate) in order to the MethodInfo for the delegate. Assuming you are not passing an anonymous typed delegate like a Lambda function, you can use this MethodInfo to get the class type using DeclaringType like so:

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

    }

Upvotes: 3

Wiktor Zychla
Wiktor Zychla

Reputation: 48230

An easiest way would be to ask for delegate's Method property that points to a method being executed.

Note that while it works for static and instance members, it doesn't necessarily make much sense when called on an anonymous delegate (when a meaningless name of a compiler-created method is returned):

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

The output:

Foo1.Method called
Foo2.Method called
Program.<Main>b__0 called

Upvotes: 4

Related Questions