是否有可能通过反射来区分纯吸气剂属性和表达式主体属性?
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?
首先,我们必须定义我们的条款:
=>
语法实现的属性。{...}
语法实现的属性。值得注意的是,有可能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是自动属性