区分仅获取属性和表达式主体属性?

问题描述 投票:2回答:1

是否有可能通过反射来区分纯吸气剂属性和表达式主体属性?

class MyClass
{
    DateTime GetterOnly { get; }

    DateTime ExpressionBody => DateTime.Now;
}

例如,如何完成下面的方法?

enum PropertyKind
{
    NotInteresting,

    GetterOnly,

    ExpressionBody,
}

PropertyKind GetPropertyKind(PropertyInfo propertyInfo)
{
    if (propertyInfo.GetSetMethod(true) == null)
    {
        // what goes here??
    }

    return PropertyKind.NotInteresting;
}

相关文章:What is the difference between getter-only auto properties and expression body properties?

c# .net reflection .net-4.0 c#-7.0
1个回答
0
投票

首先,我们必须定义我们的条款:

  • 自动属性-带有由编译器自动生成的后备字段。
  • Expression-bodied属性-一种使用=>语法实现的属性。
  • 功能强大的属性-一种使用常规{...}语法实现的属性。

值得注意的是,有可能not区分表达式主体属性和函数主体属性,因为实际上将为两者生成相同的IL。

但是,我相信您真正想要的是能够分辨自动属性和非自动属性之间的区别。

这是可能的,因为编译器会生成一个以[CompilerGeneratedAttribute]修饰并具有从属性派生的名称的后备字段,可以对其进行测试。

后备字段名称当前始终为“ k__BackingField”,。Net 4.6和.Net Core 3.1均是如此-但是当然,这绝不能保证永不更改,因此依赖于此的任何代码都可能打破C#编译器的未来版本。

尽管有很大的警告,但是您可以编写一种方法来检查PropertyInfo是否实现了自动属性,例如:

public static bool IsAutoProperty(PropertyInfo property)
{
    string backingFieldName = $"<{property.Name}>k__BackingField";
    var    backingField     = property.DeclaringType.GetField(backingFieldName, BindingFlags.NonPublic | BindingFlags.Instance);

    return backingField != null && backingField.GetCustomAttribute(typeof(CompilerGeneratedAttribute)) != null;
}

这将检查属性以查看(a)它具有一个具有从属性名称派生的特定名称的后备字段,并且(b)该后备字段是由编译器生成的。

我不认为这是一个好主意,因为它依赖于未记录且凭经验确定的编译器行为,因此需要小心!

这里是一个可编译的控制台应用程序,用于演示:

using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace ConsoleApplication1
{
    static class Program
    {
        static void Main(string[] args)
        {
            var type = typeof(MyClass);

            foreach (var property in type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
            {
                if (IsAutoProperty(property))
                    Console.WriteLine($"{property.Name} is an auto-property");
            }
        }

        public static bool IsAutoProperty(PropertyInfo property)
        {
            string backingFieldName = $"<{property.Name}>k__BackingField";
            var    backingField     = property.DeclaringType.GetField(backingFieldName, BindingFlags.NonPublic | BindingFlags.Instance);

            return backingField != null && backingField.GetCustomAttribute(typeof(CompilerGeneratedAttribute)) != null;
        }
    }

    class MyClass
    {
        DateTime GetterOnly { get; }

        DateTime ExpressionBody => DateTime.Now;
    }
}                                                                                                 

此输出:

GetterOnly是自动属性

© www.soinside.com 2019 - 2024. All rights reserved.