Ieri mi è capitato di dover recuperare tutti i "campi"
pubblici e non di una classe, della sua classe base, della base della sua
base, della... vabè, ci siamo capiti!
Non veniva volutamente considerata l'ereditarietà multipla (d'altronde non è
contemplata neanche nelle CLS).
Il modo che ho trovato io, che probabilmente sarà ben lungi dall'essere
definito come il migliore, è semplicemente quello fare la ricerca in tute le
classi base fino ad arrivare al null.
Un pochino di attenzione hanno meritato i campi protected, che sono
giustamente visibili nella classe derivata, ma lo sono anche nella classe base.
Il flag BindingFlags.NonPublic giustamente recupera sia quelli privati che
quelli protetti e per capire se sono protected (ed escluderli, in quanto
presenti già nella classe derivata) basta verificare che non siano nè pubblici,
nè privati!
Se può interessare allego un esempietto:
class ReflectionTests
{
public static void DoTest()
{
Type t = typeof(BB);
BindingFlags flags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
bool includeProtected = true;
Console.WriteLine("----------------------------------------");
while (t != null)
{
Console.WriteLine(string.Concat("Type: ", t.Name));
WriteFields(t, flags, includeProtected);
flags = BindingFlags.Instance | BindingFlags.NonPublic;
includeProtected = false;
Console.WriteLine("----------------------------------------");
t = t.BaseType;
}
}
private static void WriteFields(Type t, BindingFlags flags, bool includeProtected)
{
FieldInfo[] fields = t.GetFields(flags);
Console.WriteLine("Fields:");
foreach (FieldInfo f in fields)
{
if (includeProtected || (f.IsPrivate || f.IsPublic))
{
Console.WriteLine(string.Format("Name: {0} | IsPrivate: {1} | IsPublic: {2}", f.Name, f.IsPrivate, f.IsPublic));
}
}
Console.WriteLine();
}
}
class AA : MyBase
{
public string aaPublicField = string.Empty;
private string aaPrivateField = string.Empty;
protected string aaProtectedField = string.Empty;
}
class BB : AA
{
private string bbPrivateField = string.Empty;
private string bbProtectedField = string.Empty;
private string bbPublicField = string.Empty;
}
class MyBase
{
private string basePrivateField = string.Empty;
protected string baseProtectedField = string.Empty;
}