问题
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