不从的GetType获取字段()。GetFields与BindingFlag.Default
-
18-09-2019 - |
题
我使用,以便在反射类获取的某个对象内的所有字段。 然而我的问题是,它完美地工作时这些字段是一个正常的类中,如:
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
有两个字段; PrivateString
和ProtectedString
。类型B
有一个; ProtectedString
,它从A
继承。如果你想通过类型PrivateString
“到达” B
,则需要导航到它的基类型(b.GetType().BaseType
)。
不过请注意,即使类型B
报告,有一个叫做ProtectedString
场,本场依然没有在B
声明;它是在A
声明。这可以通过添加BindingFlags.DeclaredOnly
于上述示例程序的GetFields
呼叫进行检查; GetFields
将不返回字段B
,两个用于A
。
,这意味着该类型test3
不包含的字段test2
和test3
,因为它们是私有的类型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);