我使用,以便在反射类获取的某个对象内的所有字段。 然而我的问题是,它完美地工作时这些字段是一个正常的类中,如:

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

下面我得到既TEST1和TEST2,我的问题是,我使用的抽象并且因此几类组合。

我是这样的:

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;
}

但是,当我运行它,我不明白的领域从GetType().GetFields(BindingFlag.Default)回来。

这些字段的每个人都还具有附加到它的性质,get; set;。 当我运行的代码,我得到的性能一路回test1的但不是实际的领域。

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

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

我也尝试:

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

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

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

foreach (PropertyInfo property in properties)

任何想法,为什么我从抽象类的属性而不是字段?

有帮助吗?

解决方案

编辑:要获得的基本型民营的成员,你必须:

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

再次编辑:运

修改13年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));
}

其他提示

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

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));

    }
}

此程序的输出如下所示:

B Fields:
ProtectedString
A Fields:
PrivateString
ProtectedString

因此,式A有两个字段; PrivateStringProtectedString。类型B有一个; ProtectedString,它从A继承。如果你想通过类型PrivateString“到达” B,则需要导航到它的基类型(b.GetType().BaseType)。

不过请注意,即使类型B报告,有一个叫做ProtectedString场,本场依然没有在B声明;它是在A声明。这可以通过添加BindingFlags.DeclaredOnly于上述示例程序的GetFields呼叫进行检查; GetFields将不返回字段B,两个用于A

翻译成你的代码示例

,这意味着该类型test3不包含的字段test2test3,因为它们是私有的类型test2(字段名称和类型名称的相似性让那句话有点混乱,我怕).A

您可以使用此扩展方法来递归遍历一个类型的继承层次一路攀升到对象,有效返回类型的所有领域和所有祖先:

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;
    }
}

(未经测试,YMMV)

属性继承,字段不是。受保护的领域是可见的子类,而不是由他们继承。换句话说,在子类中实际上有它的基类的属性,但它仅仅是能看到的字段。

如果你只是想为这两个属性和字段的名称,使用

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));
}

所有类型字段包括从基类私有成员的计数。

public static IEnumerable<FieldInfo> EnumerateFields(this Type type, BindingFlags flags) =>
   type.BaseType?.EnumerateFields(flags)
       .Concat(type.GetFields(flags | BindingFlags.DeclaredOnly)) ??
   type.EnumerateFields(flags);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top