Содержание
При разработке программ в C# бывает необходимым определить имеется ли у экземпляра класса определенное свойство, проверить или записать его значение. Для выполнения этих и других операций мы можем воспользоваться классом из System.Reflection
PropertyInfo
. Этот класс предоставляет подробную информацию о свойстве класса или объекта.
Объект исследования
Допишем наш класс Person
, используемый в прошлой статье, следующим образом:
class Account { public string Login { get; set; } public string Password { get; set; } } class Person { public Person() { Account = new Account(); } public Person(string name, string family, byte age):this() { Name = name; Family = family; Age = age; } public string Name { get; set; } public string Family { get; set; } private byte age; public byte Age { get { return age; } set { if (value > 100) throw new Exception("Возраст человека не может быть больше 100 лет"); else age = value; } } public Account Account { get; private set; } }
Как можно увидеть, у нашего класса определено свойство Account
, которое представляет собой т.н. вложенный тип.
Как найти определенное свойство класса в C#
Чтобы найти определенное свойство класса можно воспользоваться методом GetProperty()
, например, следующим образом:
Person user = new Person("Вася", "Пупкин", 18); user.Account.Login = "Uasya"; user.Account.Password = "password"; Type type = user.GetType(); PropertyInfo property = type.GetProperty("AcCoUnt", BindingFlags.IgnoreCase | BindingFlags.Instance| BindingFlags.Public); if (property != null) Console.WriteLine("Свойство найдено"); else Console.WriteLine("Свойство не найдено");
Здесь следует обратить внимание на выставленные флаги BindingFlags
. Используя связку BindingFlags.IgnoreCase | BindingFlags.Instance| BindingFlags.Public
, мы пробуем найти публичное свойство, игнорируя регистр букв в имени. Поэтому результатом выполнения этого кода будет следующая строка:
Если свойство обнаружено, то, используя методы и свойства класса PropertyInfo
мы можем его детально исследовать:
Person user = new Person("Вася", "Пупкин", 18); user.Account.Login = "Uasya"; user.Account.Password = "password"; Type type = user.GetType(); PropertyInfo property = type.GetProperty("AcCoUnt", BindingFlags.IgnoreCase | BindingFlags.Instance| BindingFlags.Public); if (property != null) { Console.WriteLine("Свойство найдено"); Console.WriteLine($"Тип свойства: {property.PropertyType}"); Console.WriteLine($"Доступно для чтения: {property.CanRead}"); Console.WriteLine($"Доступно для записи: {property.CanWrite}"); bool isClass = property.PropertyType.IsClass; Console.WriteLine($"Свойство является классом: {isClass}"); if (isClass) { Console.WriteLine($"Перечисляем свойства класса {property.PropertyType.Name}"); foreach (PropertyInfo info in property.PropertyType.GetProperties()) { Console.WriteLine($" {info.PropertyType.Name} {info.Name}"); } } } else Console.WriteLine("Свойство не найдено");
Результат работы:
Тип свойства: Reflection.Account
Доступно для чтения: True
Доступно для записи: True
Свойство является классом: True
Перечисляем свойства класса Account
String Login
String Password
Получив информацию о конкретном свойстве мы можем получить или записать его значение для указанного экземпляра (объекта).
Как получить значение свойства объекта в C#
Попробуем прочитать значение найденного свойства. Для этого воспользуемся методом GetValue()
у PropertyInfo
. Допишем наш пример следующим образом:
[...] if (isClass) { Console.WriteLine($"Перечисляем свойства класса {property.PropertyType.Name}"); foreach (PropertyInfo info in property.PropertyType.GetProperties()) { Console.WriteLine($" {info.PropertyType.Name} {info.Name} Значение свойства: {info.GetValue(property.GetValue(user))}"); } } [...]
Результат выполнения программы:
Тип свойства: Reflection.Account
Доступно для чтения: True
Доступно для записи: True
Свойство является классом: True
Перечисляем свойства класса Account
String Login Значение свойства: Uasya
String Password Значение свойства: password
Здесь стоит обратить внимание на то, как мы получили значение свойства. Для того, чтобы получить значение свойства мы должны обязательно передать в метод экземпляр (объект) исследуемого класса. В нашем случае, это объект с именем user
. Таким образом, вначале мы использовали метод GetValue()
для того, чтобы получить объект Account
из объекта user
и только затем мы передали значение свойства Account
в метод GetValue()
, чтобы прочитать значение свойств Login
и Password
.
Конечно, в реальном проекте мы можем столкнуться с ситуацией, когда свойство какого-либо класса само является классом, а этот класс содержит в себе свойство, которое также является классом и т.д., то есть вложенность объектов в исследуемом экземпляре может быть самая разная. В этом случае код приложения (если использовать способ приведенный выше) станет весьма и весьма запутанным. Но,можно воспользоваться следующим приемом, чтобы получить информацию о свойстве:
private static PropertyInfo GetProperty(object t, string PropertName) { if (t.GetType().GetProperties().Count(p => p.Name == PropertName.Split('.')[0]) == 0) throw new ArgumentNullException(string.Format("Property {0}, is not exists in object {1}", PropertName, t.ToString())); if (PropertName.Split('.').Length == 1) return t.GetType().GetProperty(PropertName); else return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Split('.')[1]); }
В приведенном методе необходимо указать ссылку на экземпляр класса (объект) и имя свойства, которое необходимо найти, при этом вложенность свойства определяется точками, например:
PropertyInfo property = GetProperty(user, "Account.Login");
В данном случае, мы пробуем получить информацию о свойстве Login
, которое относится к объекту Account
, который, в свою очередь является свойством объекта user
.
Как записать значение свойства объекта в C#
Для записи значения свойства нам необходимо воспользоваться методом SetValue()
. Например:
Person user = new Person("Вася", "Пупкин", 18); user.Account.Login = "Uasya"; user.Account.Password = "password"; Type type = user.GetType(); PropertyInfo property = type.GetProperty("Name"); if (property != null) { Console.WriteLine($"Старое значение свойства {property.GetValue(user)}"); property.SetValue(user, "Петя"); Console.WriteLine($"Новое значение свойства {property.GetValue(user)}"); }
Итого
Для работы со свойствами классов и объектов C# используется класс PropertyInfo
. Используя экземпляры этого класса мы можем получить детальную информацию о свойстве, а также прочитать или записать его значение для определенного экземпляра класса, используя, соответственно, методы GetValue()
и SetValue()
.