Cercetarea câmpurilor și proprietăților folosind reflecția
Obținerea informațiilor despre câmpuri
Pentru extragerea tuturor câmpurilor, se folosește metoda GetFields(), care returnează o matrice de obiecte de clasă FieldInfo.
Câteva dintre principalele proprietăți și metode ale clasei FieldInfo:
- IsFamily: returnează true dacă câmpul are modificatorul de acces protected
- IsFamilyAndAssembly: returnează true dacă câmpul are modificatorul de acces private protected
- IsFamilyOrAssembly: returnează true dacă câmpul are modificatorul de acces protected internal
- IsAssembly: returnează true dacă câmpul are modificatorul de acces internal
- IsPrivate: returnează true dacă câmpul are modificatorul de acces private
- IsPublic: returnează true dacă câmpul are modificatorul de acces public
- IsStatic: returnează true dacă câmpul este static
- Metoda GetValue(): returnează valoarea câmpului
- Metoda SetValue(): setează valoarea câmpului
De exemplu, să obținem toate câmpurile unei clase:
using System.Reflection;
Type myType = typeof(Person);
Console.WriteLine("Câmpuri:");
foreach (FieldInfo field in myType.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
{
string modificator = "";
if (field.IsPublic)
modificator += "public ";
else if (field.IsPrivate)
modificator += "private ";
else if (field.IsAssembly)
modificator += "internal ";
else if (field.IsFamily)
modificator += "protected ";
else if (field.IsFamilyAndAssembly)
modificator += "private protected ";
else if (field.IsFamilyOrAssembly)
modificator += "protected internal ";
if (field.IsStatic) modificator += "static ";
Console.WriteLine($"{modificator}{field.FieldType.Name} {field.Name}");
}
class Person
{
static int minAge = 0;
string name;
int age;
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
public void Print() => Console.WriteLine($"{name} - {age}");
}
Pentru a obține atât câmpurile statice, cât și cele non-statice, publice și non-publice, în metoda GetFields() se transmite un set de flaguri:
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static
Ieșirea consolei:
Câmpuri:
private String name
private Int32 age
private static Int32 minAge
Obținerea și modificarea valorii câmpului
Pentru a obține un câmp după nume, se folosește metoda GetField(), căreia i se transmite numele câmpului:
var name = myType.GetField("name", BindingFlags.Instance | BindingFlags.NonPublic);
Ca al doilea parametru opțional, se transmite un set de flaguri.
Reflecția permite obținerea și modificarea valorilor chiar și pentru câmpurile private. De exemplu, să obținem și să modificăm valoarea câmpului name:
using System.Reflection;
Type myType = typeof(Person);
Person tom = new Person("Tom", 37);
var name = myType.GetField("name", BindingFlags.Instance | BindingFlags.NonPublic);
var value = name?.GetValue(tom);
Console.WriteLine(value); // Tom
name?.SetValue(tom, "Bob");
tom.Print(); // Bob - 37
class Person
{
static int minAge = 1;
string name;
int age;
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
public void Print() => Console.WriteLine($"{name} - {age}");
}
Proprietăți
Pentru extragerea tuturor proprietăților de tip, se folosește metoda GetProperties(), care returnează o matrice de obiecte PropertyInfo. Pentru a obține o proprietate după nume, se folosește metoda GetProperty(), căreia i se transmite numele proprietății și care returnează un obiect PropertyInfo?.
Câteva dintre principalele funcționalități ale clasei PropertyInfo:
- Attributes: returnează colecția de atribute ale proprietății
- CanRead: returnează true dacă proprietatea poate fi citită
- CanWrite: returnează true dacă proprietatea poate fi scrisă
- GetMethod: returnează get-accesorul sub formă de obiect MethodInfo?
- SetMethod: returnează set-accesorul sub formă de obiect MethodInfo?
- PropertyType: returnează tipul proprietății
- Metoda GetValue(): returnează valoarea proprietății
- Metoda SetValue(): setează valoarea proprietății
Folosim câteva proprietăți PropertyInfo pentru a obține informații despre proprietăți:
using System.Reflection;
Type myType = typeof(Person);
foreach (PropertyInfo prop in myType.GetProperties(
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
{
Console.Write($"{prop.PropertyType} {prop.Name} {{");
if (prop.CanRead) Console.Write("get;");
if (prop.CanWrite) Console.Write("set;");
Console.WriteLine("}");
}
class Person
{
public string Name { get; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public void Print() => Console.WriteLine($"{Name} - {Age}");
}
Ieșirea consolei:
System.String Name {get;}
System.Int32 Age {get;set;}
Cu ajutorul metodelor PropertyInfo, se poate manipula valoarea proprietății. De exemplu, să obținem și să modificăm valoarea proprietății:
using System.Reflection;
Type myType = typeof(Person);
Person tom = new Person("Tom", 37);
var ageProp = myType.GetProperty("Age");
var age = ageProp?.GetValue(tom);
Console.WriteLine(age); // 37
ageProp?.SetValue(tom, 22);
tom.Print(); // Tom - 22
class Person
{
public string Name { get; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public void Print() => Console.WriteLine($"{Name} - {Age}");
}
Pentru a obține valoarea unei proprietăți, în metoda GetValue() a obiectului PropertyInfo se transmite obiectul de la care se apelează proprietatea. Rezultatul metodei este valoarea proprietății. Pentru a seta valoarea, în metoda SetValue() a obiectului PropertyInfo se transmite obiectul căruia i se setează proprietatea și noua valoare a acesteia.