C# 查找传递给函数的变量名

C# 查找传递给函数的变量名,c#,asp.net,.net,C#,Asp.net,.net,让我用下面的例子来解释我的问题: public string ExampleFunction(string Variable) { return something; } string WhatIsMyName = "Hello World"; string Hello = ExampleFunction(WhatIsMyName); 当我将变量WhatIsMyName传递给ExampleFunction时,我希望能够获得原始变量名称的字符串。也许是这样的: Va

让我用下面的例子来解释我的问题:

public string ExampleFunction(string Variable) {
    return something;
}

string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(WhatIsMyName);
当我将变量
WhatIsMyName
传递给
ExampleFunction
时,我希望能够获得原始变量名称的字符串。也许是这样的:

Variable.OriginalName.ToString()
output += sMessages(aErrors, "errors");

有什么办法吗?

没有。我想没有

您使用的变量名是为了方便和可读性。编译器不需要它&如果我没弄错的话,就把它扔掉


如果有帮助,您可以使用属性
Name
Param
定义一个名为
NamedParameter
的新类。然后将此对象作为参数传递。

您想要的东西不能直接实现,但可以在C#3.0中使用表达式:

public void示例函数(表达式f){
Console.WriteLine((f.Body作为MemberExpression.Member.Name);
}
ExampleFunction(x=>WhatIsMyName);

请注意,这依赖于未指定的行为,虽然它在Microsoft当前的C#和VB编译器中、在Mono的C#编译器中以及在Mono的C#编译器中都能工作,但不能保证它在将来的版本中不会停止工作。

简单的答案是不。。。除非你真的很有动力

实现这一点的唯一方法是通过反射和堆栈遍历。您必须获得一个堆栈帧,找出调用函数的位置,然后使用CodeDOM尝试找到树的正确部分,以查看表达式是什么


例如,如果调用是ExampleFunction(“a”+“b”)?

否。对字符串变量的引用会传递给该函数——其中没有任何固有的metadeta。即使是反射也不能让你走出困境——从一个引用类型向后工作并不能让你获得足够的信息来做你需要做的事情

最好回到这张图纸上


rp

您可以使用反射来获取对象的所有属性,然后在其中循环,并获取属性的值,其中属性的名称与传入的参数相匹配。

Well有一点外观。当然,您不能使用任何类型信息。 此外,局部变量的名称在运行时不可用
因为它们的名称没有被编译到程序集的元数据中。

没有,但是每当您发现自己在做这样极其复杂的事情时,您可能需要重新考虑您的解决方案。请记住,代码应该比编写代码更容易阅读。

System.Environment.StackTrace将为您提供一个包含当前调用堆栈的字符串。您可以解析它以获得信息,其中包括每个调用的变量名

谢谢您的回复。我想我只能接受我现在所做的

对于那些想知道我为什么问上述问题的人。我有以下功能:

string sMessages(ArrayList aMessages, String sType) {
    string sReturn = String.Empty;
    if (aMessages.Count > 0) {
        sReturn += "<p class=\"" + sType + "\">";
        for (int i = 0; i < aMessages.Count; i++) {
            sReturn += aMessages[i] + "<br />";
        }
        sReturn += "</p>";
    }
    return sReturn;
}
如您所见,我的变量称为aErrors,我的css类称为errors。我希望我的cold能够根据我发送的变量名来确定使用哪个类


再次感谢您的回复。

GateKiller,我的解决方法有什么问题吗?您可以简单地重写函数以使用它(我已经冒昧地动态改进了函数):

静态字符串smessage(表达式amessage){
var messages=aMessages.Compile();
如果(messages.Count==0){
返回“”;
}
StringBuilder ret=新的StringBuilder();
字符串sType=((MemberExpression)aMessages.Body).Member.Name;
ret.AppendFormat(“

”,sType); foreach(消息中的字符串msg){ 添加(味精); ret.Append(“
”); } ret.Append(“

”); 返回ret.ToString(); }
可以这样称呼:

var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);
public string ExampleFunction(string variableName) {
    //Construct your log statement using c# 6.0 string interpolation
    return $"Error occurred in {variableName}";
}

string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(nameof(WhatIsMyName));
var errors=newlist(){“Hi”,“foo”};
var ret=sMessages(()=>错误);
静态void Main(字符串[]args)
{
WriteLine(“名称为“{0}”,GetName(新的{args}));
Console.ReadLine();
}
静态字符串GetName(T项),其中T:class
{
var properties=typeof(T).GetProperties();
强制执行(properties.Length==1);
返回属性[0]。名称;
}
更多详细信息可通过以下三种方式获得:

1) 完全没有思考的东西:

GetParameterName1(new { variable });

public static string GetParameterName1<T>(T item) where T : class
{
    if (item == null)
        return string.Empty;

    return item.ToString().TrimStart('{').TrimEnd('}').Split('=')[0].Trim();
}
GetParameterName1(新的{variable});
公共静态字符串GetParameterName1(T项),其中T:class
{
如果(项==null)
返回字符串。空;
返回项.ToString().TrimStart('{').trimsend('}').Split('=')[0].Trim();
}
2) 使用反射,但这比其他两种要快得多

GetParameterName2(new { variable });

public static string GetParameterName2<T>(T item) where T : class
{
    if (item == null)
        return string.Empty;

    return typeof(T).GetProperties()[0].Name;
}
GetParameterName2(新的{variable});
公共静态字符串GetParameterName2(T项),其中T:class
{
如果(项==null)
返回字符串。空;
返回typeof(T).GetProperties()[0].Name;
}
3) 最慢的,不要使用

GetParameterName3(() => variable);

public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
    if (expr == null)
        return string.Empty;

    return ((MemberExpression)expr.Body).Member.Name;
}
GetParameterName3(()=>变量);
公共静态字符串GetParameterName3(表达式表达式)
{
if(expr==null)
返回字符串。空;
返回((MemberExpression)expr.Body).Member.Name;
}
要获得组合参数名称和值,可以扩展这些方法。当然,如果将参数作为另一个参数单独传递,则很容易获得值,但这并不雅观。相反:

(一)

公共静态字符串getParameterInfo(T项),其中T:class
{
如果(项==null)
返回字符串。空;
var param=item.ToString().TrimStart('{').TrimEnd('}').Split('=');
返回“参数:”+param[0].Trim()+
“'=”+参数[1]。修剪();
}
(二)

公共静态字符串getParameterInfo(T项),其中T:class
{
如果(项==null)
返回字符串。空;
var param=typeof(T).GetProperties()[0];
返回“参数:”+参数名+
“'=”+参数GetValue(项,空);
}
(三)

公共静态字符串getParameterInfo(表达式expr)
{
if(expr==null)
返回字符串.E
GetParameterName2(new { variable });

public static string GetParameterName2<T>(T item) where T : class
{
    if (item == null)
        return string.Empty;

    return typeof(T).GetProperties()[0].Name;
}
GetParameterName3(() => variable);

public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
    if (expr == null)
        return string.Empty;

    return ((MemberExpression)expr.Body).Member.Name;
}
public static string GetParameterInfo1<T>(T item) where T : class
{
    if (item == null)
        return string.Empty;

    var param = item.ToString().TrimStart('{').TrimEnd('}').Split('=');
    return "Parameter: '" + param[0].Trim() +
           "' = " + param[1].Trim();
}
public static string GetParameterInfo2<T>(T item) where T : class
{
    if (item == null)
        return string.Empty;

    var param = typeof(T).GetProperties()[0];
    return "Parameter: '" + param.Name +
           "' = " + param.GetValue(item, null);
}
public static string GetParameterInfo3<T>(Expression<Func<T>> expr)
{
    if (expr == null)
        return string.Empty;

    var param = (MemberExpression)expr.Body;
    return "Parameter: '" + param.Member.Name +
           "' = " + ((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value);
}
public static class Utility
{
    public static Tuple<string, TSource> GetNameAndValue<TSource>(Expression<Func<TSource>> sourceExpression)
    {
        Tuple<String, TSource> result = null;
        Type type = typeof (TSource);
        Func<MemberExpression, Tuple<String, TSource>> process = delegate(MemberExpression memberExpression)
                                                                    {
                                                                        ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
                                                                        var name = memberExpression.Member.Name;
                                                                        var value = ((FieldInfo)memberExpression.Member).GetValue(constantExpression.Value);
                                                                        return new Tuple<string, TSource>(name, (TSource) value);
                                                                    };

        Expression exception = sourceExpression.Body;
        if (exception is MemberExpression)
        {
            result = process((MemberExpression)sourceExpression.Body);
        }
        else if (exception is UnaryExpression)
        {
            UnaryExpression unaryExpression = (UnaryExpression)sourceExpression.Body;
            result = process((MemberExpression)unaryExpression.Operand);
        }
        else
        {
            throw new Exception("Expression type unknown.");
        }

        return result;
    }


}
    /*ToDo : Test Result*/
    static void Main(string[] args)
    {
        /*Test : primivit types*/
        long maxNumber = 123123;
        Tuple<string, long> longVariable = Utility.GetNameAndValue(() => maxNumber);
        string longVariableName = longVariable.Item1;
        long longVariableValue = longVariable.Item2;

        /*Test : user define types*/
        Person aPerson = new Person() { Id = "123", Name = "Roy" };
        Tuple<string, Person> personVariable = Utility.GetNameAndValue(() => aPerson);
        string personVariableName = personVariable.Item1;
        Person personVariableValue = personVariable.Item2;

        /*Test : anonymous types*/
        var ann = new { Id = "123", Name = "Roy" };
        var annVariable = Utility.GetNameAndValue(() => ann);
        string annVariableName = annVariable.Item1;
        var annVariableValue = annVariable.Item2;

        /*Test : Enum tyoes*/
        Active isActive = Active.Yes;
        Tuple<string, Active> isActiveVariable = Utility.GetNameAndValue(() => isActive);
        string isActiveVariableName = isActiveVariable.Item1;
        Active isActiveVariableValue = isActiveVariable.Item2;
    }
int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);
testVar: 1
testBoolVar: True
    public Dictionary<string, string> nameOfAlreadyAcessed = new Dictionary<string, string>();
    public string nameOf(object obj, int level = 1)
    {
        StackFrame stackFrame = new StackTrace(true).GetFrame(level);
        string fileName = stackFrame.GetFileName();
        int lineNumber = stackFrame.GetFileLineNumber();
        string uniqueId = fileName + lineNumber;
        if (nameOfAlreadyAcessed.ContainsKey(uniqueId))
            return nameOfAlreadyAcessed[uniqueId];
        else
        {
            System.IO.StreamReader file = new System.IO.StreamReader(fileName);
            for (int i = 0; i < lineNumber - 1; i++)
                file.ReadLine();
            string varName = file.ReadLine().Split(new char[] { '(', ')' })[1];
            nameOfAlreadyAcessed.Add(uniqueId, varName);
            return varName;
        }
    }
var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like
var myVariable = 123.Named("my variable");
var name = myVariable.Name();
public static class ObjectInstanceExtensions
{
    private static Dictionary<object, string> namedInstances = new Dictionary<object, string>();

    public static void Named<T>(this T instance, Expression<Func<T>> expressionContainingOnlyYourInstance)
    {
        var name = ((MemberExpression)expressionContainingOnlyYourInstance.Body).Member.Name;
        instance.Named(name);            
    }

    public static T Named<T>(this T instance, string named)
    {
        if (namedInstances.ContainsKey(instance)) namedInstances[instance] = named;
        else namedInstances.Add(instance, named);
        return instance;
    }        

    public static string Name<T>(this T instance)
    {
        if (namedInstances.ContainsKey(instance)) return namedInstances[instance];
        throw new NotImplementedException("object has not been named");
    }        
}
public string ExampleFunction(string variableName) {
    //Construct your log statement using c# 6.0 string interpolation
    return $"Error occurred in {variableName}";
}

string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(nameof(WhatIsMyName));
GetParameterName2(new { variable });

//Hack to assure compiler warning is generated specifying this method calling conventions
[Obsolete("Note you must use a single parametered AnonymousType When Calling this method")]
public static string GetParameterName<T>(T item) where T : class
{
    if (item == null)
        return string.Empty;

    return typeof(T).GetProperties()[0].Name;
}
var trace = new StackTrace(true).GetFrame(1);
var line = File.ReadAllLines(trace.GetFileName())[trace.GetFileLineNumber()];
var argumentNames = line.Split(new[] { ",", "(", ")", ";" }, 
                               StringSplitOptions.TrimEntries)
                        .Where(x => x.Length > 0)
                        .Skip(1).ToList();