Recently Karl added the ability to view the non-public fields of objects in our Mole visualizer, a feature he termed BlackOps. However when reviewing it, I noticed that some fields that I know exist were not being displayed. What we were doing – targetType.GetFields(BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.DeclaredOnly) – seemed to be right but it didn’t return the results expected.
So lets take a look at an example.
public class A
private string _private;
internal string _internal;
protected string _protected;
internal protected string _internalProtected;
public class B : A
If we check the results of GetFields for these two types:
int aFieldCount = typeof(A).GetFields(BindingFlags.Instance | BindingFlags.NonPublic).Length;
int bFieldCount = typeof(B).GetFields(BindingFlags.Instance | BindingFlags.NonPublic).Length;
When you execute this code, you will find that aFieldCount is 4 but bFieldCount is 3. This is obviously not what we want for Mole since we’re looking to display all the field values (including those not visible to the type itself). The problem is that GetFields will only return Private fields if they are defined by that type – it will not return the private fields of any base classes. The solution is pretty simple – only get the fields defined by each type and walk up the BaseType chain. To get only the fields defined on the type, we add in the BindingFlags.DeclaredOnly flag and then we just use a loop to walk up the base types.
Type type = typeof(B);
int fieldCount = 0;
while (null != type)
fieldCount += type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).Length;
type = type.BaseType;