How do I get the name of a property from a propert

2020-02-06 03:02发布

I know I could have an attribute but that's more work than I want to go to... and not general enough.

I want to do something like

class Whotsit
{
    private string testProp = "thingy";

    public string TestProp 
    {
        get { return testProp; }
        set { testProp = value; }
    }

}

...

Whotsit whotsit = new Whotsit();
string value = GetName(whotsit.TestProp); //precise syntax up for grabs..

where I'd expect value to equal "TestProp"

but I can't for the life of me find the right reflection methods to write the GetName method...

EDIT: Why do I want to do this? I have a class to store settings read from a 'name', 'value' table. This is populated by a generalised method based upon reflection. I'd quite like to write the reverse...

/// <summary>
/// Populates an object from a datatable where the rows have columns called NameField and ValueField. 
/// If the property with the 'name' exists, and is not read-only, it is populated from the 
/// valueField. Any other columns in the dataTable are ignored. If there is no property called
/// nameField it is ignored. Any properties of the object not found in the data table retain their
/// original values.
/// </summary>
/// <typeparam name="T">Type of the object to be populated.</typeparam>
/// <param name="toBePopulated">The object to be populated</param>
/// <param name="dataTable">'name, 'value' Data table to populate the object from.</param>
/// <param name="nameField">Field name of the 'name' field'.</param>
/// <param name="valueField">Field name of the 'value' field.</param>
/// <param name="options">Setting to control conversions - e.g. nulls as empty strings.</param>

public static void PopulateFromNameValueDataTable<T>
        (T toBePopulated, System.Data.DataTable dataTable, string nameField, string valueField, PopulateOptions options)
    {
        Type type = typeof(T);
        bool nullStringsAsEmptyString = options == PopulateOptions.NullStringsAsEmptyString;

        foreach (DataRow dataRow in dataTable.Rows)
        {
            string name = dataRow[nameField].ToString();
            System.Reflection.PropertyInfo property = type.GetProperty(name);
            object value = dataRow[valueField];

            if (property != null)
            {
                Type propertyType = property.PropertyType;
                if (nullStringsAsEmptyString && (propertyType == typeof(String)))
                {
                    value = TypeHelper.EmptyStringIfNull(value);
                }
                else
                {
                    value = TypeHelper.DefaultIfNull(value, propertyType);
                }

                property.SetValue(toBePopulated, System.Convert.ChangeType(value, propertyType), null);
            }
        }
    }

FURTHER EDIT: I am just in code, have an instance of Whotsit and I want to get the text string of the 'TestProp' property. It seems kind of weird I know, I can just use the literal "TestProp" - or in the case of my class to datatable function I'd be in a foreach loop of PropertyInfos. I was just curious...

The original code had string constants, which I found clumsy.

7条回答
何必那么认真
2楼-- · 2020-02-06 03:20

The GetProperties on the Type class will give you the list of properties on that type.

Type t = whotsit.GetType();
PropertyInfo[] pis = t.GetProperties();
查看更多
兄弟一词,经得起流年.
3楼-- · 2020-02-06 03:33

I don't think it's possible, the only way to do this is to iterate over properties:

class TestClass
{
    private string _field;

    public string MyProperty
    {
        get { return _field; }
    }
}
class Program
{
    static void Main(string[] args)
    {
        TestClass test = new TestClass();
        PropertyInfo[] info = test.GetType().GetProperties();
        foreach(PropertyInfo i in info)
            Console.WriteLine(i.Name);
        Console.Read();
    }
}
查看更多
再贱就再见
4楼-- · 2020-02-06 03:34

FYI, I tried to serialize it to see if, by chance, that contains the property name, but no luck.

Non-working code below:

Whotsit w = new Whotsit();
XmlSerializer xs = new XmlSerializer(w.TestProp.GetType());
TextWriter sw = new StreamWriter(@"c:\TestProp.xml");
xs.Serialize(sw, w.TestProp);
sw.Close();
查看更多
时光不老,我们不散
5楼-- · 2020-02-06 03:36

No, there's nothing to do this. The expression whotsit.TestProp will evaluate the property. What you want is the mythical "infoof" operator:

// I wish...
MemberInfo member = infoof(whotsit.TestProp);

As it is, you can only use reflection to get the property by name - not from code. (Or get all the properties, of course. It still doesn't help you with your sample though.)

One alternative is to use an expression tree:

Expression<Func<string>> = () => whotsit.TestProp;

then examine the expression tree to get the property.

If none of this helps, perhaps you could tell us more about why you want this functionality?

查看更多
再贱就再见
6楼-- · 2020-02-06 03:36

It is possible (without reflection) but only with latest C# 3.0

quick & very very dirty

class Program
{
    static void Main()
    {
        string propertyName = GetName(() => AppDomain.CurrentDomain);
        Console.WriteLine(propertyName); // prints "CurrentDomain"
        Console.ReadLine();
    }

    public static string GetName(Expression<Func<object>> property)
    {
        return property.Body.ToString().Split('.').Last();
    }
}

Update: I've just realized that Jon Skeet (anyone surprised? :) has covered this possibility already but I'll keep my answer here just in case someone is interested in some example to start with.

查看更多
我欲成王,谁敢阻挡
7楼-- · 2020-02-06 03:40

Kpollack, you said in an earlier comment:

which still won't give me the ability to get the name of a property from an instance of it.

This leads me to believe that you somehow have a reference to a property. How did you get this reference? What is its type? Could you provide a code sample? If it's a PropertyInfo object, you already have what you need; since this doesn't appear to be the case, we're dealing with something else, and I'd be very interested to see what it is that you do have to work with.

P.S. Forgive me for seeming obtuse: it's early, I haven't had enough coffee, and I don't have my IDE in front of me. :-/

查看更多
登录 后发表回答