MEF и ShadowCopying DLL, чтобы я мог перезаписать их во время выполнения
Я пытаюсь остановить приложение блокировки DLL в моем каталоге плагинов MEF, чтобы я мог перезаписывать сборки во время выполнения (обратите внимание, что я на самом деле не пытаюсь перезагрузить MEF на лету, при следующем запуске приложения это нормально, я просто не хочу останавливать приложение, чтобы сделать копию)
Я пытаюсь сделать это, создав теневой скопированный домен приложения для моих загруженных mef-сборок, как показано ниже:
[Serializable]
public class Composer:IComposer
{
private readonly string _pluginPath;
public Composer(IConfigurePluginDirectory pluginDirectoryConfig)
{
_pluginPath = pluginDirectoryConfig.Path;
var setup = new AppDomainSetup();
setup.ShadowCopyFiles = "true"; // really??? is bool not good enough for you?
var appDomain = AppDomain.CreateDomain(AppDomain.CurrentDomain.FriendlyName + "_PluginDomain", AppDomain.CurrentDomain.Evidence, setup);
appDomain.DoCallBack(new CrossAppDomainDelegate(DoWorkInShadowCopiedDomain));
}
private void DoWorkInShadowCopiedDomain()
{
// This work will happen in the shadow copied AppDomain.
var catalog = new AggregateCatalog();
var dc = new DirectoryCatalog(_pluginPath);
catalog.Catalogs.Add(dc);
Container = new CompositionContainer(catalog);
}
public CompositionContainer Container { get; private set; }
}
а затем получить доступ к моему каталогу компонентов MEF через CompositionContainer этого класса. Однако контейнер состава кажется инициализированным только внутри области shadowcopy (что имеет смысл), а это значит, что его нуль в моем домене приложения. Я просто задавался вопросом, есть ли лучший способ сделать это или каким-то образом перекрещивать запрос домена, чтобы получить мои компоненты MEF.
Ответы
Ответ 1
Если вы не хотите следовать решению от Dan Bryant и zync, вы можете создать приложение оболочки, которое просто выполнит ваше приложение в новом AppDomain
.
Подход:
- Создайте новый проект приложения, который будет оболочкой.
- В приложении оболочки создайте
AppDomain
, включите теневое копирование и, если хотите, укажите каталог, в котором будет включено теневое копирование.
- Используйте
AppDomain.ExecuteAssembly
для вызова вашего текущего приложения.
Если вместо приложения у вас есть библиотека классов, вы можете попробовать следующее:
- Создайте новый проект библиотеки классов.
-
Добавьте следующий интерфейс в новый проект библиотеки классов:
public interface IRemoteLoader
{
void Load();
void Unload();
}
-
Добавьте реализацию этого интерфейса в библиотеку классов, которая должна быть выполнена в новом AppDomain. В методах Load
и Unload
вы должны добавить код для выполнения инициализации и очистки соответственно. Сделайте класс из MarshalByRefObject
. Это необходимо для .NET Remoting для создания прокси-объектов на обоих AppDomains.
-
После создания нового AppDomain используйте CreateInstanceAndUnwrap
, чтобы создать экземпляр класса загрузчика с шага 3.
-
Используйте Load
и Unload
для объекта, созданного с шага 4.
Этого будет достаточно, если вы не используете мелкозернистый контроль и достаточно просто запустить/остановить.
Ответ 2
Этот сценарий ближе к функции автоматического обновления в мобильных приложениях. По сути, вы хотите собрать новые сборки, если они доступны в приложении Start/Restart.
Одним из способов разработки этого может быть наличие механизма связи для подачи сигнала в ваше приложение при запуске новых сборок (возможно, файла version.txt). Если да, то тот же файл version.txt может указывать на новое расположение сборок. Да - вы можете создать несколько подпапок, чтобы указать на правильную версию, но они могут быть очищены другим процессом.
вы можете использовать иерархическую структуру, например:
Версия \
- Версия1.0 \
- Version2.0\
Этот тип дизайна будет ближе к хорошо знакомой парадигме автоматического обновления.
Ответ 3
Есть ли у вас возможность не использовать DirectoryCatalog и использовать AssemblyCatalog для загрузки всех сборок в каталоге? Вы даже можете пойти в код plex и скопировать тот же код из класса DirectoryCatalog, который читает через каталог и загружает сборки.
Вы потеряли бы способность загружать их на лету, но, как вы упомянули, это не требование.