0

We need to implement custom software analytics to trace the usage of the application. We have a common Command base class so the idea if to trace there something that allows us to know which command has been executed.

Consider the following sample code on a WPF Window with 1 Button:

public partial class MainWindow : Window
{
    private readonly Command _commandName = new Command();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        _commandName.Execute();
    }
}

public class Command
{
    public void Execute()
    {
        MessageBox.Show(this.GetCommandName());
        // ....
    }

    private string GetCommandName()
    {
        string commandName = null;

        MethodBase method = new StackTrace(new StackFrame(2)).GetFrame(0).GetMethod();
        Type callingType = method.DeclaringType;

        if (callingType != null)
        {
            IList<FieldInfo> variables = callingType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetField | BindingFlags.Instance).Where(f => f.FieldType == typeof(Command)).ToList();

            if (variables.Count == 1)
            {
                commandName = variables[0].Name;
            }
        }

        return commandName;
    }
}

This code will show the variable name but only if there is one Command variable on the calling type. Is there a way of getting the calling variable name directly without going thru reflection?

The output of this code is (and should be) _commandName not Button_Click.

Ignacio Soler Garcia
  • 21,122
  • 31
  • 128
  • 207
  • As the duplicate I mentioned, the second answer says that CallerMemberName is from C# 5 so it fits your requirements – Camilo Terevinto May 09 '17 at 11:20
  • Unless you can get compiler support, it *will* require Reflection; it's just that there are API functions you can call that hide the Reflection from you. Beware that needing this information is generally a design smell. – Cody Gray - on strike May 09 '17 at 11:29
  • @CamiloTerevinto: unless I miss something it is not a duplicate. I do not need the name of the method called, I need the name of the variable that executed the method because the name of the variable is the name of the Command, not the name of the method where the Command is called. Check the expected output added to my code – Ignacio Soler Garcia May 09 '17 at 11:44
  • @IgnacioSolerGarcia from where do you expect to get the name of the variable that made the call? Reflection could help you, but I think you should not depend on that, a simple F2 will kill your logic... – Camilo Terevinto May 09 '17 at 11:47
  • @CodyGray: I'm trying to find what funcions of our application are used by users and I'm doing a first and cheap approach of logging the names of the commands executed. – Ignacio Soler Garcia May 09 '17 at 11:47
  • 1
    BTW, voted for reopening since it is not really a duplicate – Camilo Terevinto May 09 '17 at 11:49
  • @CamiloTerevinto: from the same place where I get the name of the method maybe? I really don't know what functionalities are currently available. The code I posted works but only in some scenarios, I'm looking for a way that works everywhere. – Ignacio Soler Garcia May 09 '17 at 11:50
  • @IgnacioSolerGarcia maybe this can help you: http://stackoverflow.com/a/27535766/3932049 – Camilo Terevinto May 09 '17 at 11:52

1 Answers1

1

Try CallerMemberNameAttribute, e.g.

public void IDo([CallerMemberName] string methodName = null)
{
  // now methodName has the caller.
}
zaitsman
  • 8,984
  • 6
  • 47
  • 79
  • 1
    You could have just flagged as duplicate or at least explained that CallerMemberName is available from C# 5... – Camilo Terevinto May 09 '17 at 11:21
  • I am not looking for the name of the method that called this method but the name of the instance. Check my edit. – Ignacio Soler Garcia May 09 '17 at 11:46
  • @IgnacioSolerGarcia Reflection is your only friend here. But if you use DotFuscator or similar then you will get a `_a` or `_b` back. Why does your code need the name of the field? this seems a very fragile logic – zaitsman May 09 '17 at 12:03
  • I'm trying to find what funcions of our application are used by users and I'm doing a first and cheap approach of logging the names of the commands executed. No obfuscation here. – Ignacio Soler Garcia May 09 '17 at 13:16