【问题标题】:How do I get the name of a property from a property in C# (2.0)如何从 C# (2.0) 中的属性中获取属性的名称
【发布时间】:2010-09-28 04:12:40
【问题描述】:

我知道我可以有一个属性,但这比我想做的要多……而且不够笼统。

我想做类似的事情

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..

我期望值​​等于“TestProp”的地方

但我一辈子都找不到正确的反射方法来编写 GetName 方法...

编辑:我为什么要这样做?我有一个类来存储从“名称”、“值”表中读取的设置。这是由基于反射的通用方法填充的。我很想写反...

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

进一步编辑:我只是在代码中,有一个 Whotsit 实例,我想获取“TestProp”属性的文本字符串。我知道这似乎有点奇怪,我可以只使用文字“TestProp” - 或者在我的类到数据表函数的情况下,我会在 PropertyInfos 的 foreach 循环中。我只是好奇...

原始代码有字符串常量,我觉得很笨拙。

【问题讨论】:

标签: c# reflection properties


【解决方案1】:

仅供参考,我尝试对其进行序列化以查看是否偶然包含属性名称,但没有运气。

下面的非工作代码:

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

【讨论】:

    【解决方案2】:

    您尝试做的事情是不可能的。使用反射,您可以:

    • 从字符串名称中获取属性、字段或方法的详细信息。
    • 获取给定类型的所有属性、字段或方法的列表。

    您的 GetName 方法在调用时会传递一个字符串。 GetMethod 将知道字符串,但不保留源属性元数据。

    出于兴趣,你为什么要这样做?

    【讨论】:

      【解决方案3】:

      Kpollack,你在之前的评论中说过:

      这仍然无法让我从属性的实例中获取属性的名称。

      这使我相信您以某种方式引用了某个属性。你是怎么得到这个参考的?它的类型是什么?你能提供一个代码示例吗?如果它是一个 PropertyInfo 对象,那么你已经拥有了你需要的东西;由于情况似乎并非如此,我们正在处理其他事情,我很想看看您确实必须处理什么。

      附:原谅我看起来很迟钝:现在还早,我还没有喝足够的咖啡,而且我面前没有我的 IDE。 :-/

      【讨论】:

      • 我只是在代码中,有一个 Whotsit 实例,我想获取“TestProp”属性的文本字符串。我知道这似乎有点奇怪,我可以只使用文字“TestProp” - 或者在我的类到数据表函数的情况下,我会在 PropertyInfos 的 foreach 循环中。我只是好奇。
      【解决方案4】:

      这是可能的(无需反射),但仅限于最新的 C# 3.0

      快速且非常脏

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

      更新:我刚刚意识到Jon Skeet(有人感到惊讶吗?:) 已经涵盖了这种可能性,但我会在此处保留我的答案,以防有人对某些示例感兴趣开始吧。

      【讨论】:

      • 还需要.NET 3.5(OP状态2.0)
      • 我知道,但这是一个很好的通用问题,使用 .NET 3.5 的人可能对此感兴趣。
      • 我同意,对我没有多大用处,但可能对其他来找的人有用。
      【解决方案5】:

      我认为这是不可能的,唯一的方法是遍历属性:

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

      【讨论】:

      • 这仍然无法让我从属性的实例中获取属性的名称。
      【解决方案6】:

      不,没有什么可做的。表达式whotsit.TestProp 将评估该属性。你想要的是神话般的“infoof”运算符:

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

      事实上,您只能使用反射来按名称获取属性 - 而不是从代码中获取。 (当然,或者获取所有属性。但它仍然不能帮助您处理示例。)

      另一种方法是使用表达式树:

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

      然后检查表达式树以获取属性。

      如果这些都没有帮助,也许您可​​以告诉我们更多关于您为什么需要此功能的信息?

      【讨论】:

        【解决方案7】:

        GetProperties on the Type class 将为您提供该类型的属性列表。

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

        【讨论】:

        • 是的,但对我想做的事情没有多大用处,因为它是我所追求的名字的字符串......
        猜你喜欢
        • 1970-01-01
        • 2018-11-16
        • 2012-01-08
        • 2021-12-04
        • 2021-06-09
        • 1970-01-01
        • 2013-06-07
        • 2011-05-20
        • 1970-01-01
        相关资源
        最近更新 更多