c# - 获取不是由编译器生成的反射字段

标签 c# .net reflection

最近在写一个使用Reflection构建类间依赖关系图的方法,发现如下问题。我的方法分析属性的返回类型、类定义的泛型参数和这些类的实例字段。

为了检查类的实例字段,我使用以下方法。

public static IEnumerable<FieldInfo> GetFields(Type classType)
{
    return classType
        .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}  

为了测试它,我编写了以下类定义:

static void Main(string[] args)
{
    foreach (var fieldInfo in GetFields(typeof(A)))
        Console.WriteLine(fieldInfo.Name);

    Console.ReadKey();
}

class A
{
    private ulong? _field1;

    public byte PropertyA { get; set; }

    public int PropertyB { get; set; }

    public bool PropertyC { get; set; }
}

看到结果,我震惊了几秒钟。就在这时,我想起了 .NET 生成一个实例字段、Set 和 Get 方法来模拟属性。

enter image description here

当我用 .NET Reflector 检查时查看编译器生成的代码的库,我找到了如下定义。

class A
{
    private ulong? _field1; 

    [CompilerGenerated]
    private Byte <PropertyA>k__BackingField;

    [CompilerGenerated]
    private Int32 <PropertyB>k__BackingField;

    [CompilerGenerated]
    private bool <PropertyC>k__BackingField;
}

所以我修改了方法以排除具有 CompilerGenerated 属性且他的名称与某些属性匹配的字段。

public static IEnumerable<FieldInfo> GetFields(Type classType)
{
    var regex = new Regex(@"^<(?<PropertyName>\w+)>\w+$");

    var fieldInfoes = classType
            .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

    foreach (var fieldInfo in fieldInfoes)
    {
        if (fieldInfo.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
            yield return fieldInfo;
        else
        {
            var match = regex.Match(fieldInfo.Name);
            if (!match.Success) 
                continue;

            var propertyName = match.Groups[@"PropertyName"].Value;
            if (classType.GetProperty(propertyName) == null)
                yield return fieldInfo;
        }
    }
}

问题

  • 这些字段是否缺少 BindingFlags 的某种组合?
  • 还有另一种获取这些字段的方法,因为这段代码在我看来就像用火箭筒杀死蚊子一样?

完整代码可以下载here .

最佳答案

您需要的字段是:!field.IsDefined(typeof(CompilerGeneratedAttribute), false)

public static IEnumerable<FieldInfo> GetFields(Type classType)
        {
            var allFields = classType
                .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            var definedFields = from field in allFields
                                where !field.IsDefined(typeof(CompilerGeneratedAttribute), false)
                                select field;

            return definedFields;
        }

关于c# - 获取不是由编译器生成的反射字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31528140/

相关文章:

c# - 看到一个通用的500内部错误,如何查看详细错误?

c# - 从 2 个不同的范围生成随机数

c# - MSHTML COM 单击提交按钮时出现问题

c# - 获取网络浏览器 cookie 以登录

c# - 如何使用反射获得重载的私有(private)/ protected 方法

c# - 如何使用 MediaInfo 库在 C#/.NET 中提取封面艺术?

c# - UWP:如何将参数传递给导航页面的ViewModel?

c# - Factory.StartNew 和 Task.Run 之间的不同行为?

class - 在Dart中,了解类是否已定义的最佳方法是什么?

java - 如何重写 Java API 中的类,从而使用反射改变它们的行为?