Вопрос по mef, appdomain, shadow-copy, c# – MEF и ShadowCopying DLL, чтобы я мог перезаписать их во время выполнения

11

Я пытаюсь остановить DLL-библиотеки блокировки приложений в каталоге плагинов 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

Кажется, что вы можете просто вызвать File.Copy для всех файлов в каталоге плагинов, используя свой собственный каталог теней, созданный вручную. Тогда вы просто загружаетесь с теневого пути в вашем основном домене. Dan Bryant
@DanBryant, основываясь на полученных мною ответах, я чувствую, что это лучшее решение для нас, если вы опубликуете его в качестве ответа до истечения срока действия награды, я назначу вам вознаграждение. Luke McGregor
Я думал об этом, но, насколько я понимаю, это проблема, которую должно решить теневое копирование (так что, вероятно, они имеют больше краевых случаев, связанных с этим). Знаете ли вы, если shadowcopying больше, чем просто это или делает копию вручную достаточно хорошо? Luke McGregor

Ваш Ответ

3   ответа
-1

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

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

Вы можете использовать иерархическую структуру, например, так -

Версия\  - Версия 1.0 \  - Версия 2.0 \

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

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

вы можете создать приложение оболочки, которое просто выполняет ваше приложение в новомAppDomain.

Подход был бы:

Create a new application project which will be the shell application. In the shell application, create the AppDomain, enable shadow copying and if you wish, specify the directory where shadow copying will be enabled. Use AppDomain.ExecuteAssembly to call your current application.

Если вместо приложения у вас есть библиотека классов, вы можете попробовать следующее:

Create a new class library project.

Add the following interface to the new class library project:

public interface IRemoteLoader  
{  
    void Load();  
    void Unload();  
}

Add an implementation of this interface to your class library that needs to execute in a new AppDomain. In the Load and Unload methods you should add code to perform initialization and cleanup respectively. Make the class derive from MarshalByRefObject. This is needed for .NET Remoting to create proxy objects on both AppDomains.

After you create the new AppDomain, use CreateInstanceAndUnwrap to create an instance of the loader class from step 3.

Use the Load and Unload on the object created from step 4.

Этого будет достаточно, если у вас нет детального контроля и достаточно просто запустить / остановить.

Приветствия. Я добавил другой подход, который работает с библиотеками классов.
@panosrontogainnis, да, я согласен, что это кажется наиболее поддерживаемым способом решения проблемы (т.е. начальная загрузка / shadowcopy всего приложения. К сожалению, в моем случае я не управляю начальной загрузкой (как я в NServiceBus.Hosted), так что это решение не будет работать для меня конкретно. Сказав, что я думаю, что это, вероятно, лучшее решение для других Luke McGregor
-2

ать AssemblyCatalog для загрузки всех сборок в каталоге? Вы даже можете перейти к code plex и скопировать тот же код из класса DirectoryCatalog, который читает каталог и загружает сборки.

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

@ LukeMcGregor - мое предложение не сработает. Но я немного покопался, и это не проблема MEF. Домен приложения блокирует любые затронутые сборки.stackoverflow.com/questions/2745093/overwriting-dlls-in-mef
да, вы правы, моя проблема - это не проблема MEF, а скорее проблема теневого копирования / домена приложения. Luke McGregor
Эй, @zync, возможно, мне не хватает того, что ты имеешь в виду, но как мне обойти проблему теневого копирования / кросс-приложения, реализовав мой собственный DirecoryCatalog. Есть ли способ, чтобы сказать, чтобы вытащить из отдельного домена приложения? возможно, вы могли бы добавить еще несколько деталей о том, что вы имеете в виду Luke McGregor

Похожие вопросы