Применения для размышлений

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

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

  • Учитывая конфигурационный файл с строками, например, x = "Hello World!"
    y = 5,0 - динамически задавать поля некоторого объекта config равным значениям в этом файле. (Это было то, чего я хотел бы сделать на С++, но на самом деле не мог этого сделать.)

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

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

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

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

Ответ 1

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

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

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

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

Отражение - это хорошо:)

Ответ 2

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

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;

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

Разбор командной строки. Создание объекта конфигурации на основе параметров командной строки, которые передаются.

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

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

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

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

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