Когда вы используете отражение? Модели / анти-паттерны - PullRequest
30 голосов
/ 10 января 2009

Я понимаю API отражения (в c #), но я не уверен, в какой ситуации я бы использовал его. Какие есть паттерны - анти-паттерны для использования отражения?

Ответы [ 17 ]

32 голосов
/ 10 января 2009

В одном продукте, над которым я работаю, мы часто его используем, но Reflection - сложный, медленный зверь. Не ищите места, чтобы использовать его только потому, что это звучит весело или интересно. Вы будете использовать его, когда столкнетесь с проблемой, которая не может быть решена каким-либо иным способом (динамическая загрузка сборок для плагинов или каркасов, проверка сборки, фабрики, где типы не известны при сборке и т. Д.). Конечно, стоит посмотреть учебники по отражению, чтобы увидеть, как это работает, но не попадайтесь в ловушку «иметь молоток и все, что выглядит как гвоздь». У него очень специализированные варианты использования.

27 голосов
/ 10 января 2009

Единственное место, где я использовал материал Reflection в C #, было в фабричных шаблонах, где я создаю объекты (в моем случае, сетевые прослушиватели) на основе информации файла конфигурации. В файле конфигурации указывается расположение сборок, имена типов внутри них и любые дополнительные необходимые аргументы. Фабрика подобрала этот материал и создала слушателей на его основе.

11 голосов
/ 10 января 2009

Я не знаю, является ли это шаблоном, но я использую отражение для генерации SQL из определений классов DAO.

9 голосов
/ 10 января 2009

Я использовал отражение во многих местах. Основные широкие категории включают в себя:

  1. Автоматически сгенерированные графические интерфейсы (т. Е. Редактор свойств). Вы можете зациклить свойства объекта и использовать реестр фабрик элементов пользовательского интерфейса для создания формы. Я использую атрибуты в свойствах, чтобы вести создание пользовательского интерфейса.
  2. Сериализация . Я написал фреймворки сериализации, использующие отражение для сериализации и десериализации объектов.
  3. Веб-сервисы . Подобно сериализации, я использовал рефлексию для создания и потребления сообщений SOAP, а также для генерации WSDL.
  4. Специфичные для домена языки . Интерпретируемые языки сценариев обычно связываются с объектами и методами с помощью отражения.
  5. Средства отладки . Такие инструменты могут использовать отражение, чтобы исследовать состояние объекта. Удобно для создания сообщений журнала в условиях неисправности.

Шаблоны мудрые, я не уверен, что шаблоны. Общим потоком между всеми видами использования является ссылка по имени и поздняя привязка - вы хотите привязать к члену во время выполнения. Это часто бывает, когда вы динамически загружаете сборки и не знаете, какие типы объектов вам нужно создавать / манипулировать.

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

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

8 голосов
/ 10 января 2009

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

6 голосов
/ 10 января 2009

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

  1. поиск банок / сборок в известном месте
  2. перечислять jar / сборки для классов, поддерживающих интерфейс, поддерживаемый вашим плагином
  3. создать плагин во время выполнения
3 голосов
/ 10 января 2009

Я использую его в двоичном сериализаторе ( protobuf-net ). Я использую отражение только для построения модели - когда она используется (т.е. во время [де] сериализации), она использует делегатов и т. Д. Для максимальной производительности.

Я также использовал его (вместе с ComponentModel и Reflection.Emit) в HyperDescriptor , чтобы создать ускоренный доступ к свойствам (~ 100x скорость регулярного отражения).

И по необходимости вам нужно использовать отражение, если вы строите свои собственные Expression s .

3 голосов
/ 10 января 2009

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

2 голосов
/ 10 января 2009

Я использую рефлексию в своих модульных тестах, особенно когда проверяемые объекты являются анонимными. Я также использовал его как способ легко клонировать / копировать объекты модели. Вместо того, чтобы писать код для каждого объекта модели, я могу легко создать объект определенного типа, используя отражение, опросить открытые свойства входящего объекта и вызвать сеттеры клонированных объектов, соответствующие свойствам. Я также использую его с классами, сгенерированными дизайнером, которые реализуют те же сигнатуры методов, но не имеют связанного интерфейса. В этих случаях я могу опросить объект, чтобы увидеть, есть ли у него требуемый метод, и вызвать его, если он есть. Объекты LINQ2SQL похожи на это, поэтому в моем методе OnSubmit фальшивого контекста данных я использую отражение, чтобы получить метод OnValidate и вызвать его для модульного тестирования.

2 голосов
/ 10 января 2009

+ 1 при использовании фабричного шаблона - очень мощный там.

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

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

Анти-паттерн - использовать его для доступа к свойствам, которые дизайнеры классов помечали как частные, не зная, почему они пометили их как частные. Я сделал это с помощью элемента управления DataGridView WinForms, чтобы сбросить логическую переменную, чтобы можно было перемещать столбец-компаньон при перемещении его дополнения. Еще раз, это очень круто, но этот код ужасно провалится, если новый релиз изменит это частное свойство (его вполне можно было бы пропустить в 3.0 или 3.5 ...).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...