MySQL Java JavaScript PHP Python HTML-CSS C-sharp

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.

← Lecția anterioară Lecția următoare →