В большинстве случаев доступ к закрытым (private) членам класса из вне не требуется и более того в силу целого ряда объективных причин получать его не рекомендуется. Однако в некоторых случаях это может быть полезным.
В C# существует два способа получить доступ к закрытым членам (не считая открытых методов и свойств). Это доступ из вложенного класса и рефлексия.
В рамках данной статьи мы рассмотрим только доступ к полям и свойствам. Вызов закрытых методов будет рассмотрен отдельно.
Использование вложенных классов
В C# во вложенном классе в можно получить доступ к закрытым членам экземпляра внешнего класса, а также его статическим членам. В то же время доступ к закрытым членам вложенного класса из внешнего класса невозможен.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class TestClass { private int testField; private string TestString { get; set; } private static string TestStringStatic { get; set; } class TestInnerClass { public void TestMethod() { TestClass.TestString2 = "abcdef"; TestClass tc = new(); tc.testField = 1; tc.TestString = "ABCDEF"; } public void TestMethod2(TestClass tc) { TestClass.TestString2 = "abcdef"; tc.testField = 1; string s = tc.TestString; tc.TestString = "ABCDEF"; } } } |
Данный подход в силу своего архитектурного решения далеко не всегда удобен. Но, есть альтернатива в виде рефлексии.
Рефлексия
Рефлексия позволяет получать описание типов данных во время выполнения программы. Что в свою очередь даёт возможность получить доступ к закрытым членам. В данном случае к полям и методам.
Доступ к полям осуществляется при помощи класса FieldInfo. Для примера используем класс приведённый ранее.
1 2 3 4 5 6 7 |
TestClass tc = new(); // Получаем дотсуп к полю по его имени. FieldInfo fieldInfo = typeof(TestClass).GetField("testField",BindingFlags.NonPublic|BindingFlags.Instance); // Устанавливаем значение поля. fieldInfo.SetValue(tc, 5); // Получаем значение поля. int a = (int)fieldInfo.GetValue(tc); |
Обратите внимание на флаги BindingFlags.NonPublic (член класса private, internal или protected) и BindingFlags.Instance (член класса не является статическим). Эти флаги необходимо обязательно передавать в метод GetField и притом совместно. Иначе доступ к полю не будет установлен.
Доступ к закрытому свойству при помощи класса PropertyInfo осуществляется аналогичным образом.
1 2 3 4 5 6 7 |
TestClass tc = new(); // Получение доступа к свойству по имени. PropertyInfo propertyInfo = typeof(TestClass).GetProperty("TestString", BindingFlags.NonPublic | BindingFlags.Instance); // Устанавливаем значение свойства получаем значение свойства. propertyInfo.SetValue(tc, "ABCDEF"); //Получаем значение свойства. string s = (string)propertyInfo.GetValue(tc); |
Если закрытое поле или свойство являются статическими, то нужно просто заменить флаг BindingFlags.Instance на BindingFlags.Static.
Пример для статического свойства:
1 |
PropertyInfo propertyInfo = typeof(TestClass).GetProperty("TestStringStatic", BindingFlags.NonPublic | BindingFlags.Static); |
Добавить комментарий