[ACCEPTED]-Not getting fields from GetType().GetFields with BindingFlag.Default-bindingflags
Edit: To get private members of the base type, you 4 have to:
typeof(T).BaseType.GetFields(...)
Edit again: Win.
Edit 3/22/13: Used 3 Concat
instead of Union
. Since we are specifying BindingFlags.DeclaredOnly
and 2 a type's BaseType
cannot equal itself, Union
is not needed 1 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 18 see private parts of that other type, it 17 can see protected, internal and public parts. Consider 16 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 15 is the following:
B Fields:
ProtectedString
A Fields:
PrivateString
ProtectedString
So, the type A
has two fields; PrivateString
and 14 ProtectedString
. Type B
has one; ProtectedString
, that it inherits from 13 A
. If you wish to "reach" PrivateString
through the type 12 B
, you will need to navigate to its base 11 type (b.GetType().BaseType
).
Note though, that even if the type 10 B
reports to have a field called ProtectedString
, this field 9 is still not declared in B
; it is declared 8 in A
. This can be examined by adding BindingFlags.DeclaredOnly
to 7 the GetFields
calls in the above sample program; GetFields
will 6 return no fields for B
, and two for A
.
Translated 5 to your code sample, this means that the 4 type test3
does not contain the fields test2
and test3
, since 3 they are private to the type test2
(the similarity 2 of the field names and type names make that 1 sentence somewhat confusing, I am afraid).a
You can use this extension method to recursively 3 traverse a type's inheritance hierarchy 2 all the way up to object, effectively returning 1 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 5 fields are visible to descendant classes, but 4 not inherited by them. In other words, the 3 descendant class actually has the properties 2 of its base class, but it is just able to 1 see the fields.
If you just want the names for both properties 1 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));
}
Enumeration of all type fields including 1 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);
Based on Sam's and Steve's answers this 1 is what it worked for me:
public static List<Variance> DetailedCompare<T>(this T val1, T val2)
{
try
{
List<Variance> variances = new List<Variance>();
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance |
BindingFlags.DeclaredOnly;
FieldInfo[] fi = val1.GetType().GetFields(flags);
foreach (FieldInfo f in fi)
{
var previousValue = f.GetValue(val1);
var newValue = f.GetValue(val2);
if (!Equals(previousValue, newValue))
{
Variance v = new Variance
{
Prop = f.Name,
PreviousValue = previousValue,
NewValue = newValue
};
variances.Add(v);
}
}
return variances;
}
catch
{
return null;
}
}
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.