简体   繁体   中英

C# how to get the name (in string) of a class property?

public class TimeZone
{
    public int Id { get; set; }
    public string DisplayName{ get; set; }
}

In some other class I've:

   var gmtList = new SelectList(
       repository.GetSystemTimeZones(), 
       "Id",
       "DisplayName");

Note: System.Web.Mvc.SelectList

I do not like to have to write the property name with "Id" and "DisplayName". Later in time, maybe the property name will change and the compiler will not detect this error. C# how to get property name in a string?

UPDATE 1

With the help of Christian Hayter, I can use:

var tz = new TimeZone();
var gmtList = new SelectList(
    repository.GetSystemTimeZones(), 
    NameOf(() => tz.Id), 
    NameOf(() => tz.TranslatedName));

OR

var gmtList = new SelectList(
    repository.GetSystemTimeZones(), 
    NameOf(() => new TimeZone().Id), 
    NameOf(() => new TimeZone().TranslatedName));

If someone has other idea without the need of creating a new object. Feel free to share it :) thank you.

You could create a utility method to extract the property name from an expression tree, like this:

string NameOf<T>(Expression<Func<T>> expr) {
    return ((MemberExpression) expr.Body).Member.Name;
}

Then you can call it like this:

var gmtList = new SelectList(repository.GetSystemTimeZones(),
    NameOf(() => tz.Id),
    NameOf(() => tz.DisplayName));

Note that any instance of the class will do, since you are not reading the property value, only the name.

Since C# 6.0, you can now use

var gmtList = new SelectList(
    repository.GetSystemTimeZones(), 
    nameof(TimeZone.Id),
    nameof(TimeZone.DisplayName));

(Those aren't parameters btw, they're properties.)

Well, one option is to use delegates. For example:

public class SelectList<T>
{
    public SelectList(IEnumerable<T> source,
                      Func<T, string> idProjection,
                      Func<T, string> displayProjection)
    {
        ...
    }
}

Then:

var gmtList = new SelectList<TimeZone>(repository.GetSystemTimeZones(),
                                       tz => tz.Id, tz => tz.DisplayName);

var name = (string) typeof(TimeZone).GetProperty("DisplayName").GetValue(0);

string id=typeof(TimeZone).GetProperties()[0].Name;
string displayName=typeof(TimeZone).GetProperties()[1].Name;


var gmtList = new SelectList(
   repository.GetSystemTimeZones(), 
   id,
   displayName);

this will work, unless the order in which id and displayname declared doesn't change. or else you can think of defining an attribute for the property to differentiate between id and displayname.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM