Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BindingFlags - get all of them (maximum members)

Tags:

c#

reflection

I tried to get all kind of BindingFlags (in order to get all properties):

BindingFlags ALL_BF =    BindingFlags.CreateInstance | BindingFlags.DeclaredOnly | BindingFlags.ExactBinding |  BindingFlags.FlattenHierarchy |  BindingFlags.GetField |  BindingFlags.GetProperty |  BindingFlags.IgnoreCase |  BindingFlags.IgnoreReturn |  BindingFlags.Instance | BindingFlags.InvokeMethod |  BindingFlags.NonPublic |  BindingFlags.OptionalParamBinding |  BindingFlags.Public |  BindingFlags.PutDispProperty |  BindingFlags.PutRefDispProperty | BindingFlags.SetField |  BindingFlags.SetProperty | BindingFlags.Static | BindingFlags.SuppressChangeType ;

however, this returns empty collection:

obj.GetType().GetProperties( ALL_BF ); 

when I tried:

obj.GetType().GetProperties( BindingFlags.Public );

that returned many members.

1 Can someone explain why first method didnt return result? Which one interferes with other one?

2) Which combination I should use, to get ALL (obtainable) members?

like image 343
T.Todua Avatar asked Apr 19 '18 12:04

T.Todua


2 Answers

You should try this:

//All actual properties:
obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
//or
obj.GetType().GetProperties((BindingFlags)60);

 //All binding flags (if really needed):
obj.GetType().GetProperties((BindingFlags)(-1));

As you can see, it's not the same. The reason is that the BindingFlags "filters" result both explicitly and implicitly (inverted if so). That said, if you want maximum members you should pass some basic inclusive "request" BindingFlags like Public and Instance and avoid exclusive "postfilter" BindingFlags like DeclaredOnly (excludes inherited members).

Explanation:

It's binding flags, so you most likely need none of them. I guess you think of:

GetMembers(); //Simple way described in MSDN but just syntactically equivalent

BUT! Unfortunately, parameterless version returns only public members for some reason. Then, assuming you need to pass binding flags anyway (in variable, etc.), you'll probably want:

GetMembers((BindingFlags)0); //but it's like passing BindingFlags.Default

Not so obvious, but 0 means "Nothing" (which is BindingFlags.Default), not zero BindingFlags. Then what? Maybe:

GetMembers((BindingFlags)(-1));

Then you suddenly got all the BindingFlags! But not all the members (probably none at all), because they were bound.

Apparently, BindingFlags works like switchable filters: if not specified, it's vice versa (e.g. corresponding members are discarded from the end result). So finally, you need to pass most generic of them. This will be enough for most purposes:

GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
//or
GetMembers((BindingFlags)60); //just a sum of int representations of these flags

Why -1 returns all the flags?


You need to use -1 because its binary representation is ...11111111 (for example -2 is ...11111110 etc.), which means that all of its bits are "true". This is the same like using bitwise OR (Bitwise operations) with every BindingFlags constant. You can see it for yourself by using:

Console.WriteLine(Convert.ToString(-1, 2)); //-1 is the converted value(can be variable); 2 means converting to binary

After this you only need to convert the resulted value to BindingFlags as GetMembers-like methods accept only this type.

like image 107
Servail Catseye Avatar answered Oct 21 '22 16:10

Servail Catseye


The combination of BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic used in GetProperties(...) should be enough. You may want to add BindingFlags.DeclaredOnly depending on your use-case.

(For fast debugging I use ((BindingFlags)62) to create the mentioned combination.)

like image 33
thehennyy Avatar answered Oct 21 '22 15:10

thehennyy