Подтвердить что ты не робот

Что такое Reflection и когда это хороший подход?

Что такое Reflection? Я прочитал статью в Википедии по этому вопросу, и я понимаю, что это своего рода метапрограммирование, где программа может модифицировать себя во время выполнения, но что это значит? В каких ситуациях это хороший подход и когда лучше всего использовать его?

4b9b3361

Ответ 1

Отражение - это средство, в котором вы можете запросить объект об его атрибутах во время выполнения. Например, в Python, Java и .Net есть средства, где вы можете найти переменные экземпляра или методы объекта.

Примером приложения для отражения является слой отображения O/R. Некоторые используют отражение для построения объекта путем запроса его свойств во время выполнения и динамического заполнения экземпляра. Это позволяет вам делать это программно на основе метаданных из какого-то словаря данных без необходимости перекомпилировать приложение.

Чтобы сделать простой пример, я буду использовать Python, потому что его средства отражения очень просты в использовании и включают в себя меньше шаблонов, чем те, которые имеют java или .Net.

ActivePython 2.5.2.2 (ActiveState Software Inc.) based on
Python 2.5.2 (r252:60911, Mar 27 2008, 17:57:18) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class foo:
...     def __init__(self):
...             self.x = 1
...
>>> xx = foo()      # Creates an object and runs the constructor
>>> xx.__dict__     # System metadata about the object
{'x': 1}
>>> a = xx.__dict__ # Now we manipulate the object through 
>>> a['y'] = 2      # its metadata ...
>>> print xx.y      # ... and suddenly it has a new instance variable
2                   
>>>

Теперь мы использовали базовое отражение для проверки переменных экземпляра произвольного объекта. Специальная переменная __dict__ на Python является системным свойством объекта, который имеет хеш-таблицу своих членов, связанных с именем переменной (или методом). Мы рефлексивно рассмотрели объект и использовали объекты отражения, чтобы искусственно выставить в него переменную второго экземпляра, которую мы можем отобразить, вызывая ее как переменную экземпляра.

Обратите внимание, что этот конкретный трюк не работает на Java или .Net, поскольку переменные экземпляра исправлены. Система типов этих языков не позволяет добавлять новые переменные экземпляра во время выполнения так, как это делает система ввода "утка" python. Тем не менее, вы могли бы отразить обновленное значение переменной экземпляра, которая была объявлена ​​в определении типа.

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

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

Ответ 2

Это не столько модификация кода во время выполнения, а рассмотрение объектов и прошение их выполнить код, не зная их тип статически.

Один простой способ описать это будет "несколько болезненный способ заставить статически типизированный язык вести себя динамически".

EDIT: Использует:

  • Конфигурация (например, возьмите XML файл, который задает типы и свойства, затем постройте соответствующие объекты)
  • Тестирование (модульные тесты, которые идентифицируются по имени или атрибутам)
  • Веб-службы (по крайней мере, в .NET, в основном ядре веб-службы используется много отражений)
  • Автоматическая проводка событий - предоставляет метод с соответствующим именем, например. SubmitButton_Click и ASP.NET присоединяет этот метод как обработчик события SubmitButton Click (если вы включили автоподключение)

Это хорошая идея? Ну, только когда альтернативы болезненны. Я предпочитаю статическую типизацию, когда она не мешает, - тогда вы получаете много хорошего времени компиляции, и это быстрее. Но когда вам это нужно, размышление позволяет вам делать разные вещи, которые иначе просто не были бы возможны.

Ответ 3

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

Возьмите, к примеру, инфраструктуру модульного тестирования. Класс тестового бегуна, который отвечает за выполнение всех ваших модульных тестов, заранее не знает, что вы собираетесь назвать своими методами. Все, что он знает, это то, что они будут иметь префикс "тест" (или в случае Java 5, аннотированный с помощью @Test). Поэтому, когда задан тестовый класс, он отражает этот класс, чтобы получить список всех методов в нем. Затем он выполняет итерацию через эти имена методов в виде строк и вызывает эти методы для объекта, если они начинаются с "теста". Это было бы невозможно без размышлений. И это всего лишь один пример.

Ответ 4

Отражение было полезно для меня, по крайней мере, в одном проекте, о котором я могу думать. Мы написали внутреннюю программу "Менеджер процессов", которая через определенные промежутки времени выполняет множество ключевых бизнес-процессов. Проект настроен таким образом, что ядро ​​- это всего лишь служба Windows с объектами таймера, которые срабатывают каждые 30 секунд или около того и проверяют работу.

Фактическая работа выполняется в библиотеке классов (соответственно называемой "WorkerLib" ). Мы определяем классы с общедоступными методами, которые выполняют определенные задачи (перемещение файлов вокруг, загрузка данных на удаленные сайты и т.д.). Идея заключается в том, что основная служба может вызывать методы из рабочей библиотеки, не зная ничего о методах, которые она вызывает. Это позволяет нам создавать расписание в базе данных для заданий и даже добавлять новые методы в библиотеку классов без необходимости изменять основную систему.

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

Если вам нужны дополнительные объяснения, пожалуйста, не стесняйтесь спрашивать. Это был просто лучший способ, который я мог бы придумать, чтобы объяснить реальный сценарий, где отражение действительно облегчает нам задачу.

Ответ 5

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

SqlDataReader sdr = Helper.GetReader("GetClientByID", ClientID);
Client c = new Client();
FillObject(sdr, c);
return c;

Ответ 6

Действительно, отражение следует рассматривать как своего рода усилитель для кода. Это может сделать хороший код лучше и чище, а плохой код хуже. Что оно делает? Это действительно позволяет вам писать код, что вы не полностью уверены в том, что он собирается делать в то время, когда вы его пишете. У вас есть общая идея, но она позволяет вам не кодировать, какие объекты, методы и свойства выполняются при компиляции программы.

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

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

Ответ 7

В Java это, в основном, способ создать экземпляр класса, не зная об этом раньше. Предположим, вы хотите, чтобы пользователь мог изменить файл конфигурации, добавив класс, который они хотят использовать вашей программе (скажем, у вас есть многочисленные реализации какого-либо интерфейса). С отражением вы можете создать объект на основе его имени, подписи метода и т.д., а затем переведите его в свой интерфейс.

Ответ 8

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

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

Ответ 9

Я приведу вам пример.

В качестве упражнений по программированию я написал файл для проверки файлов. Он сканирует мою музыкальную библиотеку и отображает теги id1/id2, которые меня интересуют в DataGridView. Я использую отражение, чтобы получить свойства из класса info info без кода пользовательского интерфейса, который должен знать что-либо об этом классе. Если я хочу изменить отображаемую информацию, я могу либо отредактировать класс info mp3, либо изменить его конфигурацию (в зависимости от того, как я написал класс), и не нужно обновлять интерфейс.

Это также означало, что я смог использовать Dependency Injection, чтобы использовать его с конца для отображения информации о цифровых фотографиях, просто заменив класс библиотеки данных.

Ответ 10

Отражение - это (в основном) способность программы запрашивать информацию типа, доступную компилятору. Так, например, с учетом имени типа вы можете запросить методы, которые он содержит. Затем для каждого метода вы можете запрашивать типы параметров, которые они принимают и т.д. И т.д. И т.д.

Это полезно для конфигурации времени выполнения, где у вас есть файл конфигурации, который определяет поведение вашего приложения. Конфигурация может содержать имена конкретных типов, которые вы должны использовать (как это часто бывает с контейнерами IOC). Используя отражение, вы можете создать экземпляр этого конкретного типа (через API отражения) и использовать его.

Ответ 11

Ассембли содержат модули, модули содержат типы, а типы содержат элементы. Отражение предоставляет объекты, которые инкапсулируют сборки, модули и типы. Вы можете использовать отражение для динамического создания экземпляра типа, привязки типа к существующему объекту или получения типа из существующего объекта. Затем вы можете вызвать методы типа или получить доступ к его полям и свойствам. Типичное использование отражения включает следующее:

  • Используйте Assembly для определения и загрузки сборок, загрузки модулей, которые перечислены в манифесте сборки, и найдите тип из этой сборки и создайте его экземпляр.
  • Используйте модуль для обнаружения информации, такой как сборка, содержащая модуль и классы в модуле. Вы также можете получить все глобальные методы или другие конкретные, неглобальные методы, определенные в модуле.
  • Используйте ConstructorInfo для поиска информации, такой как имя, параметры, модификаторы доступа (например, публичные или частные) и детали реализации (например, абстрактные или виртуальные) конструктора. Используйте метод GetConstructors или GetConstructor для типа для вызова конкретного конструктора.
  • Используйте MethodInfo для поиска информации, такой как имя, тип возвращаемого значения, параметры, модификаторы доступа (например, публичные или частные) и детали реализации (например, абстрактные или виртуальные) метода. Используйте метод GetMethods или GetMethod для типа для вызова определенного метода.
  • Используйте FieldInfo для обнаружения таких сведений, как имя, модификаторы доступа (например, публичные или частные) и детали реализации (например, статические) поля, а также для получения или установки значений полей.
  • Используйте EventInfo для обнаружения таких данных, как имя, тип данных обработчика событий, пользовательские атрибуты, тип объявления и отраженный тип события, а также добавлять или удалять обработчики событий.
  • Используйте PropertyInfo для обнаружения таких сведений, как имя, тип данных, тип объявления, отображаемый тип и доступный для чтения или доступный статус свойства, а также для получения или установки значений свойств.
  • Используйте параметр ParameterInfo для обнаружения информации, такой как имя параметра, тип данных, является ли параметр входным или выходным параметром и положением параметра в сигнатуре метода.