Aplicarea reflecției și investigarea tipurilor
Obținerea tuturor componentelor unui tip
Metoda GetMembers() returnează toate componentele disponibile ale unui tip sub formă de obiecte MemberInfo. Acest obiect permite extragerea anumitor informații despre componenta tipului. În particular, unele dintre proprietățile sale sunt:
- DeclaringType: returnează numele complet al tipului
- MemberType: returnează o valoare din enumerația MemberTypes: - MemberTypes.Constructor - MemberTypes.Method - MemberTypes.Field - MemberTypes.Event - MemberTypes.Property - MemberTypes.NestedType
- Name: returnează numele componentei
Aplicarea metodei GetMembers pentru a afișa toate elementele disponibile ale unui tip:
using System.Reflection; // adăugăm funcționalitatea reflecției
Type myType = typeof(Person);
foreach (MemberInfo member in myType.GetMembers())
{
Console.WriteLine($"{member.DeclaringType} {member.MemberType} {member.Name}");
}
public class Person
{
string name;
public int Age { get; set; }
public Person(string name, int age)
{
this.name = name;
this.Age = age;
}
public void Print() => Console.WriteLine($"Name: {name} Age: {Age}");
}
În acest caz, vom obține toți membrii publici ai clasei Person:
Person Method get_Age
Person Method set_Age
Person Method Print
System.Object Method GetType
System.Object Method ToString
System.Object Method Equals
System.Object Method GetHashCode
Person Constructor .ctor
Person Property Age
Observați că în acest caz obținem doar membrii publici ai clasei și nu se afișează informații despre variabila privată name. De asemenea, pentru proprietate sunt afișate metodele de acces - getter-ul (get_Age) și setter-ul (set_Age). În mod implicit, obținem toate funcționalitățile, inclusiv cele moștenite de la clasele de bază (în acest caz, funcționalitatea clasei de bază Object).
BindingFlags
În exemplul de mai sus, am folosit forma simplă a metodei GetMembers(), care extrage toate metodele publice disponibile. Dar putem folosi și o altă formă a metodei: MembersInfo[] GetMembers(BindingFlags). Enumerația BindingFlags poate accepta diverse valori:
- DeclaredOnly: obține doar metodele specificate direct în clasa curentă, metodele moștenite nu sunt extrase
- Instance: obține doar metodele instanței
- NonPublic: extrage metodele non-publice
- Public: obține doar metodele publice
- Static: obține doar metodele statice
Combinând aceste valori folosind operația bitwise OR, putem combina rezultatele. De exemplu, obținem doar componentele clasei directe fără cele moștenite, atât publice, cât și non-publice:
using System.Reflection; // adăugăm funcționalitatea reflecției
Type myType = typeof(Person);
foreach (MemberInfo member in myType.GetMembers(BindingFlags.DeclaredOnly
| BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
Console.WriteLine($"{member.DeclaringType} {member.MemberType} {member.Name}");
}
public class Person
{
string name;
public int Age { get; set; }
public Person(string name, int age)
{
this.name = name;
this.Age = age;
}
public void Print() => Console.WriteLine($"Name: {name} Age: {Age}");
}
În acest caz, vom obține un rezultat diferit:
Person Method get_Age
Person Method set_Age
Person Method Print
Person Constructor .ctor
Person Property Age
Person Field name
Person Field <Age>k__BackingField
Obținerea unei singure componente după nume
Pentru a obține o singură componentă, putem folosi metoda GetMember(), căreia îi transmitem numele componentei. Opțional, putem transmite și valorile BindingFlags.
Type myType = typeof(Person);
// obținem metoda Print
MemberInfo[] print = myType.GetMember("Print", BindingFlags.Instance | BindingFlags.Public);
foreach (MemberInfo member in print)
{
Console.WriteLine($"{member.MemberType} {member.Name}");
}
Este important de menționat că la obținerea unui membru al tipului, se returnează din nou un array de MemberInfo[], deoarece într-o clasă pot exista mai multe elemente cu același nume, de exemplu, mai multe versiuni suprasolicitate ale metodei Print.