C# 不从 GetType().GetFields 获取带有 BindingFlag.Default 的字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1155529/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 09:32:58  来源:igfitidea点击:

Not getting fields from GetType().GetFields with BindingFlag.Default

c#reflectionbindingflags

提问by Patrick

I am using the Reflection classes in order to get all the fields inside a certain object. My problem however is that it works perfectly when the fields are inside a normal class, like:

我正在使用 Reflection 类来获取某个对象内的所有字段。然而,我的问题是,当字段位于普通类中时,它可以完美运行,例如:

class test
{
   string test1 = string.Empty;
   string test2 = string.Empty;
}

Here i get both test1 and test2, my problem is that i use abstraction and thus several classes combined.

在这里我得到了 test1 和 test2,我的问题是我使用了抽象,因此组合了几个类。

I got something like:

我得到了类似的东西:

class test3 : test2
{
   string test4 = string.Empty;
   string test5 = string.Empty;
}

class test2 : test1
{
   string test2 = string.Empty;
   string test3 = string.Empty;
}
class test1
{
   string test0 = string.Empty;
   string test1 = string.Empty;
}

But when I run it, I don't get the fields back from the GetType().GetFields(BindingFlag.Default).

但是当我运行它时,我没有从GetType().GetFields(BindingFlag.Default).

Everyone of those fields also have a property, get; set;attached to it. When I run the code, I get the properties all the way back to test1 but not the actual fields.

这些字段中的每一个都有一个属性,get; set;附加到它。当我运行代码时,我将属性一直返回到 test1,但不是实际字段。

This is the code that I'm trying to get the fields with:

这是我试图获取字段的代码:

FieldInfo[] fields = Obj.GetType().GetFields(BindingFlags.Default);
foreach (FieldInfo field in fields)

I have also tried:

我也试过:

FieldInfo[] fields = Obj.GetType().GetFields(BindingFlags.Public 
                                             | BindingFlags.Instance 
                                             | BindingFlags.NonPublic 
                                             | BindingFlags.Static);

I use the same code for the properties:

我对属性使用相同的代码:

PropertyInfo[] properties = Obj.GetType().GetProperties(BindingFlags.Public 
                                             | BindingFlags.Instance 
                                             | BindingFlags.NonPublic 
                                             | BindingFlags.Static);

foreach (PropertyInfo property in properties)

Any ideas why I get the properties from the abstracted classes but not the fields?

为什么我从抽象类中获取属性而不是从字段中获取属性?

采纳答案by Sam Harwell

Edit: To get privatemembers of the base type, you have to:

编辑:要获取基本类型的私有成员,您必须:

typeof(T).BaseType.GetFields(...)

Edit again: Win.

再次编辑:赢。

Edit 3/22/13: Used Concatinstead of Union. Since we are specifying BindingFlags.DeclaredOnlyand a type's BaseTypecannot equal itself, Unionis not needed and is more expensive.

2013 年 3 月 22 日编辑:Concat代替Union. 由于我们正在指定BindingFlags.DeclaredOnly并且类型BaseType不能等于自身,Union因此不需要并且更昂贵。

public static IEnumerable<FieldInfo> GetAllFields(Type t)
{
    if (t == null)
        return Enumerable.Empty<FieldInfo>();

    BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | 
                         BindingFlags.Static | BindingFlags.Instance | 
                         BindingFlags.DeclaredOnly;
    return t.GetFields(flags).Concat(GetAllFields(t.BaseType));
}

回答by David M

Properties are inherited, fields are not. Protected fields are visible to descendant classes, but not inherited by them. In other words, the descendant class actually has the properties of its base class, but it is just able to see the fields.

属性是继承的,字段不是。受保护的字段对后代类可见,但不被它们继承。换句话说,后代类实际上具有其基类的属性,但它只能看到字段。

回答by Fredrik M?rk

A type that inherits another type cannot see private parts of that other type, it can see protected, internal and public parts. Consider the following code:

继承另一个类型的类型不能看到其他类型的私有部分,它可以看到受保护的、内部的和公共的部分。考虑以下代码:

class A
{
    // note that this field is private
    string PrivateString = string.Empty;
    // protected field
    protected string ProtectedString = string.Empty;
}

class B : A { }

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("B Fields:");
        B b = new B();
        b.GetType()
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
            .ToList()
            .ForEach(f => Console.WriteLine(f.Name));

        Console.WriteLine("A Fields:");
        A a = new A();
        a.GetType()
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
            .ToList()
            .ForEach(f => Console.WriteLine(f.Name));

    }
}

The output of this program is the following:

该程序的输出如下:

B Fields:
ProtectedString
A Fields:
PrivateString
ProtectedString

So, the type Ahas two fields; PrivateStringand ProtectedString. Type Bhas one; ProtectedString, that it inherits from A. If you wish to "reach" PrivateStringthrough the type B, you will need to navigate to its base type (b.GetType().BaseType).

因此,该类型A有两个字段;PrivateStringProtectedString。类型B有一个;ProtectedString,它继承自A. 如果您希望PrivateString通过 type来“到达” B,则需要导航到其基本类型 ( b.GetType().BaseType)。

Note though, that even if the type Breports to have a field called ProtectedString, this field is still not declared in B; it is declared in A. This can be examined by adding BindingFlags.DeclaredOnlyto the GetFieldscalls in the above sample program; GetFieldswill return no fields for B, and two for A.

但请注意,即使该类型B报告有一个名为 的字段ProtectedString,该字段仍未在B; 中声明。它在A. 这可以通过添加BindingFlags.DeclaredOnlyGetFields上述示例程序中的调用来检查;GetFields不会为 返回任何字段,为 返回B两个字段A

Translated to your code sample, this means that the type test3does not contain the fields test2and test3, since they are private to the type test2(the similarity of the field names and type names make that sentence somewhat confusing, I am afraid).a

转换为您的代码示例,这意味着该类型test3不包含字段test2and test3,因为它们是该类型的私有test2字段(字段名称和类型名称的相似性使该句子有些混乱,恐怕)。

回答by Jacob

You can use this extension method to recursively traverse a type's inheritance hierarchy all the way up to object, effectively returning all fields of the type and all its ancestors:

您可以使用此扩展方法递归遍历类型的继承层次结构,直到对象,有效地返回该类型的所有字段及其所有祖先:

public static class ReflectionExtensions
{
    public static IList<FieldInfo> GetAllFields(this Type type, BindingFlags flags)
    {
        if(type == typeof(Object)) return new List<FieldInfo>();

        var list = type.BaseType.GetAllFields(flags);
        // in order to avoid duplicates, force BindingFlags.DeclaredOnly
        list.AddRange(type.GetFields(flags | BindingFlags.DeclaredOnly));
        return list;
    }
}

(Untested, YMMV)

(未经测试,YMMV)

回答by Carlo V. Dango

If you just want the names for both properties and fields, use

如果您只想要属性和字段的名称,请使用

private static IEnumerable<string > GetAllFieldsAndProperties(Type t)
{
  if (t == null)
    return Enumerable.Empty<string>();

  BindingFlags flags = BindingFlags.Public 
    | BindingFlags.NonPublic 
    | BindingFlags.Static 
    | BindingFlags.Instance 
    | BindingFlags.DeclaredOnly;
  return t.GetFields(flags).Select(x=>x.Name)
    .Union(GetAllFieldsAndProperties(t.BaseType))
    .Union(t.GetProperties(flags).Select(x=>x.Name));
}

回答by Makeman

Enumeration of all type fields including private members from base classes.

枚举所有类型字段,包括来自基类的私有成员。

public static IEnumerable<FieldInfo> EnumerateFields(this Type type, BindingFlags flags) =>
   type.BaseType?.EnumerateFields(flags)
       .Concat(type.GetFields(flags | BindingFlags.DeclaredOnly)) ??
   type.EnumerateFields(flags);