简体   繁体   English

如何从C#(2.0)中的属性获取属性的名称

[英]How do I get the name of a property from a property in C# (2.0)

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" 在哪里我期望价值等于“TestProp”

but I can't for the life of me find the right reflection methods to write the GetName method... 但我不能为我的生活找到正确的反射方法来编写GetName方法...

EDIT: Why do I want to do this? 编辑:我为什么要这样做? I have a class to store settings read from a 'name', 'value' table. 我有一个类来存储从'name','value'表中读取的设置。 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. 进一步编辑:我只是在代码中,有一个Whotsit实例,我想得到'TestProp'属性的文本字符串。 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. 我知道这似乎有点奇怪,我可以使用文字“TestProp” - 或者在我的类的情况下使用数据表函数我将在PropertyInfos的foreach循环中。 I was just curious... 我只是好奇而已...

The original code had string constants, which I found clumsy. 原始代码有字符串常量,我发现它很笨拙。

No, there's nothing to do this. 不,没有什么可以做的。 The expression whotsit.TestProp will evaluate the property. 表达式whotsit.TestProp将评估该属性。 What you want is the mythical "infoof" operator: 你想要的是神话般的“infoof”运算符:

// 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? 如果这些都没有帮助,也许你可以告诉我们更多你想要这个功能的原因?

It is possible (without reflection) but only with latest C# 3.0 它是可能的(没有反射)但只有最新的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. 更新:我刚刚意识到Jon Skeet (任何人都感到惊讶?:)已经涵盖了这种可能性,但我会在这里保留我的答案以防万一有人对一些例子感兴趣。

What you are trying to do is not possible. 你想要做的是不可能的。 Using reflection you can: 使用反射你可以:

  • Get a property, field or method's details from it's string name. 从它的字符串名称中获取属性,字段或方法的详细信息。
  • Get a list of all properties, fields or methods for a given type. 获取给定类型的所有属性,字段或方法的列表。

Your GetName method, when called, is passed a string. 调用时,GetName方法将传递一个字符串。 The GetMethod will know about the string but retains no source property meta data. GetMethod将了解字符串,但不保留源属性元数据。

Out of interest, why are you trying to do this? 出于兴趣,你为什么要这样做?

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();
    }
}

Kpollack, you said in an earlier comment: Kpollack,你在之前的评论中说过:

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; 如果它是PropertyInfo对象,那么您已经拥有了所需的东西; 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. 因为事实并非如此,我们正在处理其他问题,而且我很想知道你必须要做什么。

PS 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. PS原谅我看似迟钝:现在还早,我没有足够的咖啡,而且我没有在我面前使用我的IDE。 :-/ : - /

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();

The GetProperties on the Type class will give you the list of properties on that type. Type类上的GetProperties将为您提供该类型的属性列表。

Type t = whotsit.GetType();
PropertyInfo[] pis = t.GetProperties();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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