7

I am trying to reflect the fields in a derived type but it's returning the fields of the base type.

public class basetype
{
    string basevar;
}

public class derivedtype : basetype
{
    string derivedvar;
}

In some function:

derivedtype derived = new derivedtype();

FieldInfo[] fields = derived.GetType().GetFields();

This will return basevar, but not derivedvar. I've tried all the different bindings and it doesn't seem to make a difference.

Also, I'm doing this in ASP.NET within App_Code where basevar is defined in App_Code and derivedvar is a user control defined in App_Controls where the types are not in scope.

KenEucker
  • 4,932
  • 5
  • 22
  • 28
  • 1
    Your code worked for me (I see `derivedvar`), once I make the fields public to expose them to `GetFields()`. Are you certain of your class hierarchy? Have you tried the code above in a stand-alone project? – Michael Petrotta Oct 08 '10 at 02:23
  • 1
    In the above code, `derivedtype` doesn't even derive from `basetype`, so you should only see `derivedvar` (with BindingFlags.NonPublic), but not `basevar`. – dtb Oct 08 '10 at 02:30
  • @dtb: I'd missed that. Just reran with proper derivation; same results. – Michael Petrotta Oct 08 '10 at 02:32
  • Right, I missed the derivation in my code example. I changed it, thanks for your help. – KenEucker Oct 08 '10 at 04:21

2 Answers2

11

As is, this will return nothing as the default binding is for public fields only.

As is also, derivedtype isn't derived from basetype

With:

FieldInfo[] fields = derived.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

It returns derivedvar. I've just checked in LINQPad.

If I change derivedtype to be derived from basetype, then I can get both fields with:

FieldInfo[] fields = derived.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Concat(derived.GetType().BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)).ToArray();
Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • That was it, I was attempting to get the private members as well but I couldn't get it to work until I made the members private. Silly oversight on my part guys, sorry. – KenEucker Oct 08 '10 at 04:20
  • In my case, the above line needed a small adjustment: – Mark May 27 '19 at 11:48
5

Reflection is a bit odd.

If the members are public, all of them up the entire hierarchy are visible.

If the members are non-public, you have to specify BindingFlags.NonPublic and you will only get those members that are of the type used. Inherited members are not visible. If you want to see all the non-public members of a type you'll have to walk up the inheritence chain.

Tergiver
  • 14,171
  • 3
  • 41
  • 68
  • This is not "odd", but exactly how it should be. Imagine you could give a field in a derived class any name, except the name of a private field in the base class. Then that private field wouldn't be that private anymore. – dtb Oct 08 '10 at 02:45
  • Correct me if I am wrong, but I think you are misunderstanding the issue here. My problem is with attempting to get the derived members, it is already returning the inherited members from the base class but not returning any of the members in the derived class. I tried BindingFlags.NonPublic but it didn't work either. – KenEucker Oct 08 '10 at 03:16
  • @Epic720: as I mention above, I suspect that your class hierarchy is not as you describe (indeed it can't be - the two classes you show in your example aren't even related to each other!). Can you hack your real hierarchy down to something you can post? – Michael Petrotta Oct 08 '10 at 03:21
  • @dtb: You're right, it is as it should be. It's just not intuitive. If this is your first stab at reflection and you don't think it through, you may find it a bit odd. – Tergiver Oct 08 '10 at 13:00