Given this class:
public class MyClass
{
public int MyProperty {get; set;}
}
How will I be able to extract the name of MyProperty
in code?
For example, I am able to get the name of the class like this
typeof(MyClass).Name
How can I do something similar for the property?
The reason for the question is that I want this particular code to be resistant against refactorizations of the names.
EDIT: With resistant I mean that I want the code at the call site to be robust in the face of changes of the propertyname. I have some stuff that is using a string representation of the property name. Sorry for the poor phrasing. I did not include call site code in order to keep the problem clean and not wander off into other discussions on the nature of the call site code.
You do it like this, using compiler generated expression trees:
public static string GetMemberName<T, TValue>(Expression<Func<T, TValue>> memberAccess)
{
return ((MemberExpression)memberAccess.Body).Member.Name;
}
Now call the static method from code:
class MyClass
{
public int Field;
public string Property { get; set; }
}
var fieldName = GetMemberName((MyClass c) => c.Field);
var propertyName = GetMemberName((MyClass c) => c.Property);
// fieldName has string value of `Field`
// propertyName has string value of `Property`
You can now also use refactoring to rename that field without breaking this code
In C# 6 we can do it very simply
nameof(MyField);
you can get method\\type\\propery\\field\\class\\namespace names in the same way ex
nameof(MyClass);
nameof(namespacename1) // returns "namespacename1"
nameof(TestEnum.FirstValue) // returns enum's first value
With C# 6.0, you can use the new nameof
operator.
nameof(MyClass.MyField) // returns "MyField"
nameof(MyClass) //returns "MyClass"
See nameof (C# and Visual Basic Reference) for more examples.
Using Reflection you can find all Members from MyClass
with this.
MemberInfo[] members = typeof(MyClass).GetMembers();
Now you can find your desired property for each Member.
foreach ( MemberInfo memberInfo in members)
{
Console.WriteLine("Name: {0}", memberInfo.Name); // Name: MyField
Console.WriteLine("Member Type: {0}", memberInfo.MemberType); // Member Type: Property
}
If you want to find only Properties use PropertyInfo
instead of MemberInfo
. Or write this
foreach ( MemberInfo memberInfo in members.Where(p => p.MemberType == MemberTypes.Property))
{
Console.WriteLine("Name: {0}", memberInfo.Name); // Name: MyField
Console.WriteLine("Member Type: {0}", memberInfo.MemberType); // Member Type: Property
}
You could use the following class which contains a method using an expression tree as an argument to determine a member name based on a lambda expression:
public class MemberHelper<T>
{
public string GetName<U>(Expression<Func<T, U>> expression)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
if (memberExpression != null)
return memberExpression.Member.Name;
throw new InvalidOperationException("Member expression expected");
}
}
Then use it like so:
MemberHelper<MyClass> memberHelper = new MemberHelper<MyClass>();
string name = memberHelper.GetName(x => x.MyField);
If you only want to get name of an instance member, you can use shorter code:
public static string GetMemberName<TValue>(Expression<Func<TValue>> memberAccess)
{
return ((MemberExpression)memberAccess.Body).Member.Name;
}
And use it like the following inside the class:
ReflectionTools.GetMemberName(() => _someInstanceVariableOrProperty)
If you don't want to waste your time , try the following one. I know there will be people run into the same problem.
// Soner - tested!
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(item))
{
string name = descriptor.Name; // Name
object value = descriptor.GetValue(item); // Value
var type = descriptor.PropertyType; // Type
Console.WriteLine($"{name}={value}={type}");
}
Don't forget to add using System.ComponentModel;
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.