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:
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.
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)
.
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.
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?
Edit: To get private members of the base type, you have to:
typeof(T).BaseType.GetFields(...)
Edit again: Win.
Edit 3/22/13: Used Concat
instead of Union
. Since we are specifying BindingFlags.DeclaredOnly
and a type's BaseType
cannot equal itself, Union
is not needed and is more expensive.
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 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 A
has two fields; PrivateString
and ProtectedString
. Type B
has one; ProtectedString
, that it inherits from A
. If you wish to "reach" PrivateString
through the type B
, you will need to navigate to its base type (b.GetType().BaseType
).
Note though, that even if the type B
reports 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.DeclaredOnly
to the GetFields
calls in the above sample program; GetFields
will return no fields for B
, and two for A
.
Translated to your code sample, this means that the type test3
does not contain the fields test2
and 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
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)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With