【问题标题】:How to get the PropertyInfo of a specific property?如何获取特定属性的 PropertyInfo?
【发布时间】:2009-01-29 12:34:57
【问题描述】:

我想获取特定属性的 PropertyInfo。我可以使用:

foreach(PropertyInfo p in typeof(MyObject).GetProperties())
{
    if ( p.Name == "MyProperty") { return p }
}

但一定有办法做类似的事情

typeof(MyProperty) as PropertyInfo

有吗?还是我卡在进行类型不安全的字符串比较?

干杯。

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    有一种 .NET 3.5 方式使用 lambdas/Expression 不使用字符串...

    using System;
    using System.Linq.Expressions;
    using System.Reflection;
    
    class Foo
    {
        public string Bar { get; set; }
    }
    static class Program
    {
        static void Main()
        {
            PropertyInfo prop = PropertyHelper<Foo>.GetProperty(x => x.Bar);
        }
    }
    public static class PropertyHelper<T>
    {
        public static PropertyInfo GetProperty<TValue>(
            Expression<Func<T, TValue>> selector)
        {
            Expression body = selector;
            if (body is LambdaExpression)
            {
                body = ((LambdaExpression)body).Body;
            }
            switch (body.NodeType)
            {
                case ExpressionType.MemberAccess:
                    return (PropertyInfo)((MemberExpression)body).Member;
                default:
                    throw new InvalidOperationException();
            }
        }
    }
    

    【讨论】:

    • 不错的解决方案,但不幸的是我没有使用 .NET3.5。不过,打勾!
    • 在 2.0 中,Vojislav Stojkovic 的答案是你能得到的最接近的答案。
    • 一个问题:为什么在提取 .Body 属性之前对“body is LambdaExpression”进行测试?选择器不总是一个 LambdaExpression 吗?
    • @tigrou 很可能只是一个疏忽,也许我借用了与 Expression 有效的现有代码
    • @MarcGravell 这个实现不是很完善。在PropertyHelper&lt;Derived&gt;.GetProperty(x =&gt; x.BaseProperty); 的情况下,您不会获得正确的属性信息。见stackoverflow.com/questions/6658669/…
    【解决方案2】:

    您可以使用新的 nameof() 运算符,它是 C# 6 的一部分,可在 Visual Studio 2015 中使用。更多信息 here

    对于您的示例,您将使用:

    PropertyInfo result = typeof(MyObject).GetProperty(nameof(MyObject.MyProperty));
    

    编译器会将nameof(MyObject.MyProperty) 转换为字符串“MyProperty”,但您可以获得能够重构属性名称而无需记住更改字符串的好处,因为 Visual Studio、ReSharper 等知道如何重构nameof() 值。

    【讨论】:

    • 如果您的示例以PropertyInfo result = 开头而不是var result = 开头,可以说会更清楚一点。
    【解决方案3】:

    你可以这样做:

    typeof(MyObject).GetProperty("MyProperty")
    

    但是,由于 C# 没有“符号”类型,因此没有什么可以帮助您避免使用字符串。顺便说一句,你为什么称这种类型为不安全类型?

    【讨论】:

    • 因为它没有在编译时评估?如果我更改了我的属性名称或拼写错误的字符串,直到代码运行时我才知道。
    【解决方案4】:

    反射用于运行时类型评估。所以你的字符串常量不能在编译时验证。

    【讨论】:

    • 这就是 OP 试图避免的。不确定这是否能回答问题。
    • 关于编译时间与运行时间以及 OP 的初衷虽然避免硬编码字符串似乎仍然是最干净的解决方案,但它似乎是最干净的解决方案 - 避免了拼写错误的可能性,允许更轻松地重构并制作更简洁的代码风格。
    猜你喜欢
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多