How to check if the parameter of a method comes from a variable or a literal? [duplicate]

余生长醉 提交于 2021-02-20 05:33:32

问题


Considering this code:

string variable = "hello";

myMethod(variable) //usage 1
myMethod("hello")  //usage 2

Can I detect the difference between the these method usage above?


回答1:


Requiring debug info generated (anything but none, in debug as well as in release build mode), having the source code and to deploy it, and using Finding the variable name passed to a function adapted we can get information from the stack frame like that:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
static class InstanceHelper
{

  static private Dictionary<string, (bool, string)> AlreadyAcessedVarNames
    = new Dictionary<string, (bool, string)>();

  static public (bool isLiteral, string value) NameOfFromStack(this object instance, int level = 1)
  {
    try
    {
      var frame = new StackTrace(true).GetFrame(level);
      string filePath = frame.GetFileName();
      int lineNumber = frame.GetFileLineNumber();
      string id = filePath + lineNumber;
      if ( AlreadyAcessedVarNames.ContainsKey(id) )
        return AlreadyAcessedVarNames[id];
      using ( var file = new StreamReader(filePath) )
      {
        for ( int i = 0; i < lineNumber - 1; i++ )
          file.ReadLine();
        string name = file.ReadLine().Split('(', ')')[1].TrimEnd(' ', ',');
        bool isLiteral = true;
        if ( name.Length > 0 )
          if ( ( char.IsLetter(name[0]) || name[0] == '_' || name[0] == '@' )
            && name != "null" & name != "false" && name != "true"
            && !name.StartsWith("@\"") )
            isLiteral = false;
        var result = (isLiteral, name);
        AlreadyAcessedVarNames.Add(id, result);
        return result;
      }
    }
    catch
    {
      return (true, "Internal Error in " + nameof(NameOfFromStack));
    }
  }

}

Notes

  • The level is 1 for the current method, 2 for the caller, and so on.

  • This method considers the whole parameter list to be one here, so when there are multiple parameters, we get a list like "param1, param2, param3" and we will have to split again on name and we should also pass a position to the method to get the desired.

Test

string myString = "hello";
int a = 10;
bool b = true;

MyMethod1(null);

MyMethod1(myString);
MyMethod1("hello");

MyMethod2(a);
MyMethod2(10);

MyMethod3(b);
MyMethod3(false);

static void MyMethod1(string msg)
{
  Console.WriteLine(msg.NameOfFromStack(2));
}

static void MyMethod2(int value)
{
  Console.WriteLine(value.NameOfFromStack(2));
}

static void MyMethod3(bool value)
{
  Console.WriteLine(value.NameOfFromStack(2));
}

Output

(True, null)
(False, myString)
(True, "hello")
(False, a)
(True, 10)
(False, b)
(True, false)


来源:https://stackoverflow.com/questions/65754778/how-to-check-if-the-parameter-of-a-method-comes-from-a-variable-or-a-literal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!