WeakReference, WeakEvents: полезность для динамически загружаемых/выгружаемых серверных модулей, библиотек DLL?

Я думаю, подходят ли WeakReferences и WeakEvents в случае интерфейса серверных модулей. Может быть, это хороший дизайн?

Но вопрос также в производительности, безусловно, требуется Invoke в шаблоне WeakEvent и доступ к WeakReference, возможно, тоже

ОБНОВЛЕНИЕ: подробности

СЕРВЕР:

  • есть менеджер модулей,
  • может загружать/выгружать классы реализации DLL с общим интерфейсом, IModule,
  • поэтому диспетчер модулей создает и хранит экземпляры IModule,

Модули:

  • иметь имя или уникальный код,
  • необходимо взаимодействовать с другими модулями, использовать их методы, свойства, события,

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

Но может быть общий класс (WeakRefModule, где T: IModule) данной реализации IModule, ограниченный IModule, который может внутренне хранить WeakReference в IModule. И тогда данный модуль будет раскрывать свои общедоступные методы с помощью методов расширений или наследования на основе WeakRefModule. Скрытие экземпляра модуля за WeakReference. То же самое со свойствами и событиями (WeakEvents).

Такие модули всегда будут гарантировать, что другой модуль не сможет помешать сборке мусора.

Итак, вопрос в том, насколько это хороший дизайн и могут ли быть какие-то скрытые проблемы?


person ipavlu    schedule 03.10.2015    source источник
comment
Вы согласны с тем, что GC случайным образом удаляет подписки на события и модули?   -  person usr    schedule 03.10.2015
comment
Почему случайное удаление? Модули обычно имеют один экземпляр, хранящийся в диспетчере модулей, поэтому модуль существует, если он явно не выгружен. WeakEvents между такими модулями не будет терять подписку, если некоторые модули не будут выгружены.   -  person ipavlu    schedule 04.10.2015
comment
Я не знаю, о чем ты говоришь. Вы не детализировали свою архитектуру. О каких модулях вы говорите?   -  person usr    schedule 04.10.2015
comment
О, извините, проблема в том, что когда я перехожу к деталям, обычно мои вопросы закрываются как не вопросы, поэтому я избегал этого :). Я обновлю сам вопрос с более подробной информацией...   -  person ipavlu    schedule 04.10.2015
comment
Да, это действительно необходимо. Сейчас очень абстрактно.   -  person usr    schedule 04.10.2015


Ответы (1)


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

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

Я бы вообще не использовал здесь слабые ссылки. Вы можете создать оболочку IModule, которая просто делегирует другому IModule. Затем вы можете очистить эту оболочку, когда хотите выгрузить модуль.

class WrappedModule : IModule {
 IModule inner;

 public void Dispose() { inner = null; }

 void IModule.SomeMeth() {
  if (inner == null) throw ...;
  else inner.SomeMeth();
 }
}

Теперь вы можете пропустить объект-оболочку, но он маленький. Вы не будете вести настоящий модуль.

Модули никогда не получают прямого доступа к другим модулям. Вместо этого им передается этот класс «дескриптора». Ручку можно отключить в любой момент.

person usr    schedule 05.10.2015