问题
I am looking for a way to retrieve the variable name, so I don't have to use hard-coded declarations when needed (for property names etc.):
I hardly believe it's possible; maybe someone has a solution. Note: even not variables, properties would also be a move.
'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
Answers are welcommed in either VB or C#.
回答1:
Oh there is a simple solution, use expression trees here is an example, just adapt to your needs in c#
string GetPropertyName<T>(Expression<Func<T>> property)
{
MemberExpression ex = (MemberExpression)property.Body;
string propertyName = ex.Member.Name;
return propertyName;
}
Now you can do
String example = null;
String propertyName = GetPropertyName(()=>example.Length);
//propertyName == "Length"
The first time I've seen that, it was a revelation ! ;)
回答2:
@Abraham Pinzur; Following a further link in the article you linked to provides this snippet:
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;
}
Which does produce "Name is 'args'". Rinat's method exploits the property name generated by the C# compiler to produce an anonymous type in the expression new{args}
. The full article is here: http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html
--Edit--
Having read further into Rinat's article, this can also be done by producing an expression tree and browsing either the tree, or the IL it contains. Basically, read the linked article!
回答3:
Rinat Abdullin is doing something like this by parsing IL from an anonymous method (or lambda expression). His full code is here.
So, your example would look like:
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;
}
}
However, this does not directly extend to your second case (contact.Name
--> "Name"
).
回答4:
That's not possible. What's sent to the method in your example is not the variable itself, but only a copy of the reference that the variable contains.
The method could scan all objects that exist for the reference among member variables, but that would only be doable if the variable is a class member. Local variables are not possible to reach that way as they only exist on the stack. Also, if the same reference exist in more than one variable, the method would not be able to tell which of them was used.
In your example the Name property returns a null reference, it is of course impossible to tell where that came from.
If the variable was a value type, it would get boxed inside a new object on the heap. As the only reference to the boxed object is the one that is sent to the method, and the boxed object has no reference back to the original, there is no way of telling which variable was boxed.
来源:https://stackoverflow.com/questions/1386642/get-variable-not-hard-coded-name