Передача сообщений в рамках подключаемого модуля

Во-первых, в моем блоге есть небольшая предыстория этой проблемы:

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

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

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

  • Объект подключаемого модуля данных (реализующий инициализацию, установку и метаданные подключаемого модуля) [реализует IDataPlugin<FactoryType>]
  • Объект данных (например, учетная запись) [реализует, например, IAccount]
  • Фабрика для создания экземпляров объекта данных [реализует, например, IAccountFactory]

Ранее объект данных и объект плагина были объединены в один, но это означало, что для каждой транзакции, зарегистрированной в учетной записи, нужно было создавать новый плагин транзакции, что вызывало ряд проблем. К сожалению, этот рефакторинг нарушил передачу моего сообщения. Объект данных реализует INotifyPropertyChanged, и поэтому я столкнулся с новой проблемой, которую я не знаю, как обойти: объект подключаемого модуля регистрирует события с помощью брокера сообщений, но на самом деле срабатывают объекты данных. события. Это означает, что подключаемый модуль подписки в настоящее время должен подписываться на каждую созданную учетную запись, транзакцию и т. д.! Это явно не масштабируется.

Насколько я могу судить на данный момент, у меня есть два возможных решения:

  1. Сделайте объект подключаемого модуля данных посредником между объектами данных и брокером сообщений, возможно, группируя уведомления об изменениях. Мне это не нравится, потому что это добавляет еще один уровень сложности в систему обмена сообщениями, без которого, как мне кажется, я мог бы обойтись.
  2. Отбросьте текущую реализацию на основе событий и используйте что-то другое, более легко управляемое (WCF в памяти?!).

Так что, наверное, я действительно спрашиваю:

  1. Как бы вы решили эту проблему?
  2. Как вы думаете, какие потенциальные решения я упустил из виду?
  3. Является ли мой подход хотя бы смутно правильным/разумным?! :-)

Как вы можете судить по датам сообщений в блоге, какой-то вариант этой проблемы мучает меня уже довольно давно! Таким образом, любые ответы будут очень признательны.

Предыстория самого фреймворка такова:

Моя структура плагинов состоит из трех основных компонентов: плагин-брокер, менеджер настроек и брокер сообщений. Брокер подключаемых модулей выполняет основные функции подключаемых модулей: обнаруживает и создает подключаемые модули. Диспетчер настроек управляет пользовательскими настройками для платформы и отдельных плагинов, например, какие плагины включены, где должны быть сохранены данные и т. д. Связь осуществляется через публикацию/подписку, а брокер сообщений сидит посередине и собирает все опубликованные типы сообщений и управление подписками. Публикация/подписка в настоящее время реализуется через интерфейс .NET INotifyPropertyChanged, который предоставляет одно событие с именем PropertyChanged; брокер сообщений создает список всех подключаемых модулей, реализующих INotifyPropertyChanged, и подписывает другие подключаемые модули на это событие. Цель передачи сообщений — позволить подключаемым модулям учетных записей и транзакций уведомить подключаемые модули хранилища об изменении данных, чтобы их можно было сохранить.


person alastairs    schedule 08.09.2008    source источник


Ответы (3)


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

Вы можете создать объект типа сеанса. Каждый подключаемый модуль прослушивает события объекта сеанса. Объект данных больше не вызывает событие — он вызывает объект сеанса, чтобы вызвать событие (один из параметров должен быть объектом данных, вызывающим событие).

Это означает, что ваши плагины должны подписаться только на одно событие, но они получают событие от всех объектов данных.

С другой стороны, если только один подключаемый модуль будет одновременно прослушивать объект данных, почему бы просто не сделать так, чтобы объект данных вызывал подключаемый модуль напрямую?

person dan gibson    schedule 09.09.2008

Вау! Большой вопрос! :)

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

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

У Мартина Фаулера есть серия шаблонов событий в его блоге. Проверьте! Очень хорошее чтение.

person Marcio Aguiar    schedule 08.09.2008

Пока рано, но не думали ли вы попробовать использовать MEF вместо создания собственного?

person Dave Ward    schedule 08.09.2008