Примеры использования для размышления

StackOverflow https://stackoverflow.com/questions/49737

  •  09-06-2019
  •  | 
  •  

Вопрос

Недавно я разговаривал с коллегой о C ++ и посетовал, что нет способа взять строку с именем поля класса и извлечь поле с этим именем;другими словами, ему не хватает рефлексии.Он озадаченно посмотрел на меня и спросил, когда кому-нибудь когда-нибудь понадобится сделать подобное.

Навскидку у меня не нашлось для него подходящего ответа, кроме как "эй, мне нужно сделать это прямо сейчас".Итак, я сел и составил список некоторых вещей, которые я действительно сделал с помощью reflection на различных языках.К сожалению, большинство моих примеров взяты из моего веб-программирования на Python, и я надеялся, что у присутствующих здесь людей найдется больше примеров.Вот список, который я составил:

  1. Дан конфигурационный файл со строками типа
    x = "Привет, мир!"
    y = 5.0
    динамически задавать поля некоторых config объект, равный значениям в этом файле.(Это было то, что я хотел бы сделать на C ++, но на самом деле не смог.)

  2. При сортировке списка объектов выполняйте сортировку на основе произвольного атрибута, заданного именем этого атрибута из файла конфигурации или веб-запроса.

  3. При написании программного обеспечения, использующего сетевой протокол, reflection позволяет вызывать методы, основанные на строковых значениях из этого протокола.Например, я написал IRC-бота, который переводил бы
    !some_command arg1 arg2
    в вызов метода actions.some_command(arg1, arg2) и выведите все, что вернула эта функция, обратно на IRC-канал.

  4. При использовании функции Python __getattr__ (которая похожа на method_missing в Ruby / Smalltalk) Я работал с классом с большим количеством статистических данных, таких как late_total.Для каждой статистики я хотел иметь возможность добавлять _percent, чтобы получить эту статистику в процентах от общего количества данных, которые я подсчитывал (например, stats.late_total_percent).Размышление сделало это очень простым.

Итак, может ли кто-нибудь здесь привести какие-либо примеры из своего собственного опыта программирования, когда рефлексия была полезна?В следующий раз, когда коллега спросит меня, почему я "вообще хочу сделать что-то подобное", я хотел бы быть более подготовленным.

Это было полезно?

Решение

Я могу перечислить следующее использование для размышления:

  • Поздняя привязка
  • Безопасность (проанализируйте код по соображениям безопасности)
  • Анализ кода
  • Динамическая типизация (утиная типизация невозможна без рефлексии)
  • Метапрограммирование

Некоторые примеры отражения в реальном мире из моего личного опыта:

  • Разработанная система плагинов, основанная на рефлексии
  • Используемая модель аспектно-ориентированного программирования
  • Выполнен статический анализ кода
  • Использовались различные фреймворки внедрения зависимостей
  • ...

Рефлексия - хорошая вещь :)

Другие советы

Я использовал отражение, чтобы получить информацию о текущем методе для исключений, ведения журнала и т.д.

string src = MethodInfo.GetCurrentMethod().ToString();
string msg = "Big Mistake";
Exception newEx = new Exception(msg, ex);
newEx.Source = src;

вместо того, чтобы

string src = "MyMethod";
string msg = "Big MistakeA";
Exception newEx = new Exception(msg, ex);
newEx.Source = src;

Это просто проще для копирования / вставки наследования и генерации кода.

Сейчас я нахожусь в ситуации, когда у меня есть поток XML, поступающий по проводам, и мне нужно создать экземпляр объекта Entity, который будет заполнять себя из элементов в потоке.Проще использовать отражение, чтобы выяснить, какой объект Entity может обрабатывать тот или иной элемент XML, чем писать гигантский, требующий кошмара обслуживания условный оператор.Очевидно, что существует зависимость между XML-схемой и тем, как я структурирую и называю свои объекты, но я контролирую и то, и другое, так что это не большая проблема.

Часто вы хотите динамически создавать экземпляры и работать с объектами, тип которых неизвестен до времени выполнения.Например, с помощью OR-mappers или в архитектуре плагина.Макетные фреймворки используют его, если вы хотите написать библиотеку ведения журнала и хотите динамически проверять тип и свойства исключений.

Если я подумаю еще немного, то, вероятно, смогу привести больше примеров.

Я нахожу отражение очень полезным, если входные данные (например, xml) имеют сложную структуру, которая легко сопоставляется с экземплярами объектов, или мне нужно какое-то отношение "is a" между экземплярами.

Поскольку отражение в Java относительно простое, я иногда использую его для простых данных (сопоставления ключ-значение), где у меня есть небольшой фиксированный набор ключей.С одной стороны, легко определить, является ли ключ допустимым (если у класса есть setter setKey(строковые данные)), с другой стороны, я могу изменить тип (текстовых) входных данных и скрыть преобразование (например, простое приведение к int в getKey()), поэтому остальная часть приложения может полагаться на правильно введенные данные.Если тип некоторой пары ключ-значение изменяется для одного объекта (напримерform int to float), мне нужно только изменить его в объекте данных и его пользователях, но мне не нужно помнить о проверке синтаксического анализатора.Возможно, это не самый разумный подход, если речь идет о производительности...

Пишущие диспетчеры.Twisted использует рефлексивные возможности python для отправки вызовов XML-RPC и SOAP.RMI использует Java reflection api для отправки.

Синтаксический анализ командной строки.Создание объекта конфигурации на основе переданных параметров командной строки.

При написании модульных тестов может быть полезно использовать отражение, хотя в основном я использовал это для обхода модификаторов доступа (Java).

Я использовал отражение в C #, когда в фреймворке был какой-то внутренний или закрытый метод или сторонняя библиотека, к которой я хотел получить доступ.

(Отказ от ответственности:Это не обязательно лучшая практика, поскольку частные и внутренние методы могут быть изменены в более поздних версиях.Но это сработало для того, что мне было нужно.)

Ну, в языках со статической типизацией вы бы хотели использовать отражение каждый раз, когда вам нужно сделать что-то "динамическое".Это удобно для инструментальных целей (сканирование элементов объекта).В Java он довольно часто используется в JMX и динамических прокси.И есть масса разовых случаев, когда это действительно единственный выход (практически в любое время, когда вам нужно сделать что-то, чего компилятор вам не позволит).

Обычно я использую отражение для отладки.Отражение может более легко и точно отображать объекты в системе, чем набор инструкций для печати.Во многих языках, которые имеют первоклассные функции, вы даже можете вызывать функции объекта без написания специального кода.

Однако есть способ делать то, что вы хотите (ред.).Используйте хэш-таблицу.Сохраните поля, привязанные к имени поля.

Если бы вы действительно захотели, вы могли бы создать стандартные функции получения / установки или создать макросы, которые делают это "на лету". #define GetX() Get("X") что-то в этом роде.

Таким образом, вы могли бы даже реализовать свое собственное несовершенное отражение.

Для опытного пользователя, если вы можете скомпилировать код, возможно, удастся включить генерацию отладочных выходных данных и использовать это для выполнения отражения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top