查找传递给函数的变量名称

时间:2022-07-06 00:42:45

Let me use the following example to explain my question:

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

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

string WhatIsMyName = "Hello World"';
string Hello = ExampleFunction(WhatIsMyName);

When I pass the variable "WhatIsMyName" to the example function, I want to be able to get a string of the original variables name. Perhaps something like:

当我将变量“WhatIsMyName”传递给示例函数时,我希望能够获得原始变量名称的字符串。也许是这样的:

Variable.OriginalName.ToString()

Is there any way to do this?

有没有办法做到这一点?

16 个解决方案

#1


-6  

**No.**I don't think so.

**不。**我不这么认为。

The variable name that you use is for your convenience and readability. The compiler doesn't need it & just chucks it out if I'm not mistaken.

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

If it helps, you could define a new class called NamedParameter with attributes Name and Param. You then pass this object around as parameters.

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

#2


51  

What you want isn't possible directly but you can use Expressions in C# 3.0:

您想要的不是直接的,但您可以在C#3.0中使用表达式:

public void ExampleFunction(Expression<Func<string, string>> f) {
    Console.WriteLine((f.Body as MemberExpression).Member.Name);
}

ExampleFunction(x => WhatIsMyName);

Note that this relies on unspecified behaviour and while it does work in Microsoft’s current C# and VB compilers, and in Mono’s C# compiler, there’s no guarantee that this won’t stop working in future versions.

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

#3


33  

I know this is an old question but in C# 6.0 they Introduce the nameof Operator which should solve this issue. The name of operator resolves the name of the variable passed into it.

我知道这是一个古老的问题但是在C#6.0中他们引入了应该解决这个问题的运营商名称。运算符的名称解析传递给它的变量的名称。

Usage for your case would look like this:

您案例的用法如下所示:

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

A major benefit is that it is done at compile time,

一个主要好处是它在编译时完成,

The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).

表达式的名称是常量。在所有情况下,在编译时评估nameof(...)以生成字符串。它的参数不在运行时进行评估,并且被认为是无法访问的代码(但它不会发出“无法访问的代码”警告)。

More information can be found here

更多信息可以在这里找到

Older Version Of C 3.0 and above
To Build on Nawfals answer

旧版本的C 3.0及以上版本以Nawfals为基础回答

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

#4


17  

static void Main(string[] args)
{
  Console.WriteLine("Name is '{0}'", GetName(new {args}));
  Console.ReadLine();
}

static string GetName<T>(T item) where T : class
{
  var properties = typeof(T).GetProperties();
  Enforce.That(properties.Length == 1);
  return properties[0].Name;
}

More details are in this blog post.

更多详细信息,请参阅此博客文章。

#5


11  

Three ways:

1) Something without reflection at all:

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

2) Uses reflection, but this is way faster than other two.

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

3) The slowest of all, don't use.

3)最慢的,不要使用。

GetParameterName3(() => variable);

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

    return ((MemberExpression)expr.Body).Member.Name;
}

To get a combo parameter name and value, you can extend these methods. Of course its easy to get value if you pass the parameter separately as another argument, but that's inelegant. Instead:

要获取组合参数名称和值,可以扩展这些方法。当然,如果你将参数作为另一个参数单独传递,那么它很容易获得值,但这是不优雅的。代替:

1)

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

2)

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

3)

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

1 and 2 are of comparable speed now, 3 is again sluggish.

1和2现在具有相当的速度,3再次缓慢。

#6


4  

No, but whenever you find yourself doing extremely complex things like this, you might want to re-think your solution. Remember that code should be easier to read than it was to write.

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

#7


4  

Yes! It is possible. I have been looking for a solution to this for a long time and have finally come up with a hack that solves it (it's a bit nasty). I would not recommend using this as part of your program and I only think it works in debug mode. For me this doesn't matter as I only use it as a debugging tool in my console class so I can do:

是!有可能的。我一直在寻找解决方案很长一段时间,并最终想出一个解决它的黑客(它有点讨厌)。我不建议将此作为程序的一部分使用,我认为它只能在调试模式下使用。对我来说这没关系,因为我只在控制台类中使用它作为调试工具,所以我可以这样做:

int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);

the output to the console would be:

控制台的输出是:

testVar: 1
testBoolVar: True

Here is the function I use to do that (not including the wrapping code for my console class.

这是我用来做的功能(不包括我的控制台类的包装代码)。

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

#8


2  

System.Environment.StackTrace will give you a string that includes the current call stack. You could parse that to get the information, which includes the variable names for each call.

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

#9


2  

Well Try this Utility class,

那么试试这个Utility类,

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


}

And User It Like

和用户一样

    /*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;
    }

#10


0  

No. A reference to your string variable gets passed to the funcion--there isn't any inherent metadeta about it included. Even reflection wouldn't get you out of the woods here--working backwards from a single reference type doesn't get you enough info to do what you need to do.

不会。对你的字符串变量的引用会被传递给函数 - 它没有任何关于它的固有元数据。即使反射也不会让你走出困境 - 从单一参考类型向后工作并不能让你获得足够的信息来完成你需要做的事情。

Better go back to the drawing board on this one!

最好回到这个画板上!

rp

#11


0  

You could use reflection to get all the properties of an object, than loop through it, and get the value of the property where the name (of the property) matches the passed in parameter.

您可以使用反射来获取对象的所有属性,而不是循环遍历它,并获取属性的值(属性的名称)与传入的参数匹配。

#12


0  

Thanks for all the responses. I guess I'll just have to go with what I'm doing now.

感谢所有的回复。我想我只需要继续我现在正在做的事情。

For those who wanted to know why I asked the above question. I have the following function:

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

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

I send it an array of error messages and a css class which is then returned as a string for a webpage.

我发送了一个错误消息数组和一个css类,然后将其作为网页的字符串返回。

Every time I call this function, I have to define sType. Something like:

每次调用这个函数时,我都要定义sType。就像是:

output += sMessages(aErrors, "errors");

As you can see, my variables is called aErrors and my css class is called errors. I was hoping my cold could figure out what class to use based on the variable name I sent it.

如您所见,我的变量称为aErrors,我的css类称为错误。我希望我的冷可以根据我发送的变量名来找出要使用的类。

Again, thanks for all the responses.

再次感谢所有回复。

#13


0  

GateKiller, what's wrong with my workaround? You could rewrite your function trivially to use it (I've taken the liberty to improve the function on the fly):

GateKiller,我的解决方法有什么问题?您可以轻松地重写您的功能以使用它(我已经冒昧地改进了功能):

static string sMessages(Expression<Func<List<string>>> aMessages) {
    var messages = aMessages.Compile()();

    if (messages.Count == 0) {
        return "";
    }

    StringBuilder ret = new StringBuilder();
    string sType = ((MemberExpression)aMessages.Body).Member.Name;

    ret.AppendFormat("<p class=\"{0}\">", sType);
    foreach (string msg in messages) {
        ret.Append(msg);
        ret.Append("<br />");
    }
    ret.Append("</p>");
    return ret.ToString();
}

Call it like this:

这样叫:

var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);

#14


0  

Do this

var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like

or naming in code by hand

或手动命名代码

var myVariable = 123.Named("my variable");
var name = myVariable.Name();

using this class

使用这个类

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

Code tested and most elegant I can come up with.

代码测试和最优雅,我可以想出来。

#15


-1  

The short answer is no ... unless you are really really motivated.

简短的回答是否定的......除非你真的很有动力。

The only way to do this would be via reflection and stack walking. You would have to get a stack frame, work out whereabouts in the calling function you where invoked from and then using the CodeDOM try to find the right part of the tree to see what the expression was.

唯一的方法是通过反射和堆栈行走。你必须获得一个堆栈框架,在你调用的调用函数中找出行踪,然后使用CodeDOM尝试找到树的正确部分以查看表达式是什么。

For example, what if the invocation was ExampleFunction("a" + "b")?

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

#16


-1  

Well had a bit of look. of course you can't use any Type information. Also, the name of a local variable is not available at runtime because their names are not compiled into the assembly's metadata.

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

#1


-6  

**No.**I don't think so.

**不。**我不这么认为。

The variable name that you use is for your convenience and readability. The compiler doesn't need it & just chucks it out if I'm not mistaken.

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

If it helps, you could define a new class called NamedParameter with attributes Name and Param. You then pass this object around as parameters.

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

#2


51  

What you want isn't possible directly but you can use Expressions in C# 3.0:

您想要的不是直接的,但您可以在C#3.0中使用表达式:

public void ExampleFunction(Expression<Func<string, string>> f) {
    Console.WriteLine((f.Body as MemberExpression).Member.Name);
}

ExampleFunction(x => WhatIsMyName);

Note that this relies on unspecified behaviour and while it does work in Microsoft’s current C# and VB compilers, and in Mono’s C# compiler, there’s no guarantee that this won’t stop working in future versions.

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

#3


33  

I know this is an old question but in C# 6.0 they Introduce the nameof Operator which should solve this issue. The name of operator resolves the name of the variable passed into it.

我知道这是一个古老的问题但是在C#6.0中他们引入了应该解决这个问题的运营商名称。运算符的名称解析传递给它的变量的名称。

Usage for your case would look like this:

您案例的用法如下所示:

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

A major benefit is that it is done at compile time,

一个主要好处是它在编译时完成,

The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).

表达式的名称是常量。在所有情况下,在编译时评估nameof(...)以生成字符串。它的参数不在运行时进行评估,并且被认为是无法访问的代码(但它不会发出“无法访问的代码”警告)。

More information can be found here

更多信息可以在这里找到

Older Version Of C 3.0 and above
To Build on Nawfals answer

旧版本的C 3.0及以上版本以Nawfals为基础回答

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

#4


17  

static void Main(string[] args)
{
  Console.WriteLine("Name is '{0}'", GetName(new {args}));
  Console.ReadLine();
}

static string GetName<T>(T item) where T : class
{
  var properties = typeof(T).GetProperties();
  Enforce.That(properties.Length == 1);
  return properties[0].Name;
}

More details are in this blog post.

更多详细信息,请参阅此博客文章。

#5


11  

Three ways:

1) Something without reflection at all:

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

2) Uses reflection, but this is way faster than other two.

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

3) The slowest of all, don't use.

3)最慢的,不要使用。

GetParameterName3(() => variable);

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

    return ((MemberExpression)expr.Body).Member.Name;
}

To get a combo parameter name and value, you can extend these methods. Of course its easy to get value if you pass the parameter separately as another argument, but that's inelegant. Instead:

要获取组合参数名称和值,可以扩展这些方法。当然,如果你将参数作为另一个参数单独传递,那么它很容易获得值,但这是不优雅的。代替:

1)

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

2)

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

3)

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

1 and 2 are of comparable speed now, 3 is again sluggish.

1和2现在具有相当的速度,3再次缓慢。

#6


4  

No, but whenever you find yourself doing extremely complex things like this, you might want to re-think your solution. Remember that code should be easier to read than it was to write.

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

#7


4  

Yes! It is possible. I have been looking for a solution to this for a long time and have finally come up with a hack that solves it (it's a bit nasty). I would not recommend using this as part of your program and I only think it works in debug mode. For me this doesn't matter as I only use it as a debugging tool in my console class so I can do:

是!有可能的。我一直在寻找解决方案很长一段时间,并最终想出一个解决它的黑客(它有点讨厌)。我不建议将此作为程序的一部分使用,我认为它只能在调试模式下使用。对我来说这没关系,因为我只在控制台类中使用它作为调试工具,所以我可以这样做:

int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);

the output to the console would be:

控制台的输出是:

testVar: 1
testBoolVar: True

Here is the function I use to do that (not including the wrapping code for my console class.

这是我用来做的功能(不包括我的控制台类的包装代码)。

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

#8


2  

System.Environment.StackTrace will give you a string that includes the current call stack. You could parse that to get the information, which includes the variable names for each call.

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

#9


2  

Well Try this Utility class,

那么试试这个Utility类,

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


}

And User It Like

和用户一样

    /*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;
    }

#10


0  

No. A reference to your string variable gets passed to the funcion--there isn't any inherent metadeta about it included. Even reflection wouldn't get you out of the woods here--working backwards from a single reference type doesn't get you enough info to do what you need to do.

不会。对你的字符串变量的引用会被传递给函数 - 它没有任何关于它的固有元数据。即使反射也不会让你走出困境 - 从单一参考类型向后工作并不能让你获得足够的信息来完成你需要做的事情。

Better go back to the drawing board on this one!

最好回到这个画板上!

rp

#11


0  

You could use reflection to get all the properties of an object, than loop through it, and get the value of the property where the name (of the property) matches the passed in parameter.

您可以使用反射来获取对象的所有属性,而不是循环遍历它,并获取属性的值(属性的名称)与传入的参数匹配。

#12


0  

Thanks for all the responses. I guess I'll just have to go with what I'm doing now.

感谢所有的回复。我想我只需要继续我现在正在做的事情。

For those who wanted to know why I asked the above question. I have the following function:

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

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

I send it an array of error messages and a css class which is then returned as a string for a webpage.

我发送了一个错误消息数组和一个css类,然后将其作为网页的字符串返回。

Every time I call this function, I have to define sType. Something like:

每次调用这个函数时,我都要定义sType。就像是:

output += sMessages(aErrors, "errors");

As you can see, my variables is called aErrors and my css class is called errors. I was hoping my cold could figure out what class to use based on the variable name I sent it.

如您所见,我的变量称为aErrors,我的css类称为错误。我希望我的冷可以根据我发送的变量名来找出要使用的类。

Again, thanks for all the responses.

再次感谢所有回复。

#13


0  

GateKiller, what's wrong with my workaround? You could rewrite your function trivially to use it (I've taken the liberty to improve the function on the fly):

GateKiller,我的解决方法有什么问题?您可以轻松地重写您的功能以使用它(我已经冒昧地改进了功能):

static string sMessages(Expression<Func<List<string>>> aMessages) {
    var messages = aMessages.Compile()();

    if (messages.Count == 0) {
        return "";
    }

    StringBuilder ret = new StringBuilder();
    string sType = ((MemberExpression)aMessages.Body).Member.Name;

    ret.AppendFormat("<p class=\"{0}\">", sType);
    foreach (string msg in messages) {
        ret.Append(msg);
        ret.Append("<br />");
    }
    ret.Append("</p>");
    return ret.ToString();
}

Call it like this:

这样叫:

var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);

#14


0  

Do this

var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like

or naming in code by hand

或手动命名代码

var myVariable = 123.Named("my variable");
var name = myVariable.Name();

using this class

使用这个类

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

Code tested and most elegant I can come up with.

代码测试和最优雅,我可以想出来。

#15


-1  

The short answer is no ... unless you are really really motivated.

简短的回答是否定的......除非你真的很有动力。

The only way to do this would be via reflection and stack walking. You would have to get a stack frame, work out whereabouts in the calling function you where invoked from and then using the CodeDOM try to find the right part of the tree to see what the expression was.

唯一的方法是通过反射和堆栈行走。你必须获得一个堆栈框架,在你调用的调用函数中找出行踪,然后使用CodeDOM尝试找到树的正确部分以查看表达式是什么。

For example, what if the invocation was ExampleFunction("a" + "b")?

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

#16


-1  

Well had a bit of look. of course you can't use any Type information. Also, the name of a local variable is not available at runtime because their names are not compiled into the assembly's metadata.

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