3

我正在寻找一种检索变量名称的方法,因此我不必在需要时使用硬编码声明(对于属性名称等):

我几乎不相信这是可能的。也许有人有解决方案。注意:即使不是变量,属性也会是一个动作。

'Pseudo:
Module Module1

    Sub Main()
        Dim variable = "asdf"
        Dim contact As New Contact

        Dim v1 = GetVariableName(variable) 'returns variable
        Dim v2 = GetVariableName(contact.Name) 'returns Name

    End Sub

    Class Contact
        Public ReadOnly Property Name()
            Get
                Return Nothing
            End Get
        End Property
    End Class

    Public Function GetVariableName(variable As Object) As String
        ':}
    End Function

End Module

欢迎使用 VB 或 C# 来回答。

4

4 回答 4

5

@Abraham Pinzur;在您链接到的文章中的进一步链接之后提供了此代码段:

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();
return properties[0].Name;
}

确实会产生“名称是'args'”。Rinat 的方法利用 C# 编译器生成的属性名称在表达式中生成匿名类型new{args}。全文在这里:http ://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html

- 编辑 -

进一步阅读 Rinat 的文章后,这也可以通过生成表达式树并浏览树或它包含的 IL 来完成。基本上,阅读链接的文章!

于 2009-09-06T21:10:38.757 回答
5

哦有一个简单的解决方案,这里使用表达式树是一个例子,在c#中适应你的需要

string GetPropertyName<T>(Expression<Func<T>> property)
{
    MemberExpression ex = (MemberExpression)property.Body;
    string propertyName = ex.Member.Name;
    return propertyName;
}

现在你可以做

String example = null;
String propertyName = GetPropertyName(()=>example.Length);
//propertyName == "Length"

我第一次看到,这是一个启示!;)

于 2009-09-06T21:41:47.503 回答
3

Rinat Abdullin通过从匿名方法(或 lambda 表达式)解析 IL 来做类似的事情。他的完整代码在这里

因此,您的示例如下所示:

class Program
{
    static void Main (string[] args)
    {
        var variable = "asdf";

        var v1 = GetVariableName(() => variable);  // returns "variable"
    }

    static string GetVariableName (Func<object> variable)
    {   // Again, credit to Mr. Abdullin ...
        var il = variable.Method.GetMethodBody().GetILAsByteArray();
        var fieldHandle = BitConverter.ToInt32(il,2);
        var field = variable.Target.GetType()
                .Module.ResolveField(fieldHandle);
        return field.Name;
    }
}

但是,这不会直接扩展到您的第二种情况(contact.Name--> "Name")。

于 2009-09-06T20:40:33.820 回答
2

那是不可能的。在您的示例中发送到方法的不是变量本身,而只是变量包含的引用的副本。

该方法可以扫描所有存在的对象以在成员变量之间进行引用,但这只有在变量是类成员时才可行。局部变量不可能以这种方式到达,因为它们只存在于堆栈中。此外,如果相同的引用存在于多个变量中,该方法将无法判断使用了其中的哪一个。

在您的示例中, Name 属性返回一个空引用,当然不可能知道它来自哪里。

如果变量是值类型,它将被装箱在堆上的新对象中。由于对装箱对象的唯一引用是发送给方法的引用,并且装箱对象没有对原始对象的引用,因此无法判断哪个变量被装箱。

于 2009-09-06T21:03:13.693 回答