Каковы проблемы с запуском WPF в нескольких доменах приложений в одном потоке пользовательского интерфейса?

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

Вот пример использования MAF / System.AddIn. Какой опыт у других был с этим? Как это решение обрабатывает RoutedEvents / Commands, которые могут возникать внутри одного пользовательского элемента управления, и правильно ли они сериализуются в доменах приложений? А как насчет ресурсов WPF? Можно ли легко получить к ним доступ через домены приложений?

Ответов (2)

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

Кроме того, я полагаю, вы знаете о корпоративной библиотеке и единстве?

Есть блок приложения WPF, так что использование этого шаблона не слишком болезненно;) Но разве они не говорят: «Нет боли - нет выигрыша»?

Также существует CAB (Composite UI Application Block), объединяющий в единое целое. Люди из WPF SDK создали платформу Silverlight и WPF. (он же Призма).

Ах да, еще вы спросили о ресурсах? Я предпочитаю загружать ресурсы вручную в классе Application. Я понял одну вещь: допустим, у вас есть ResourceDictionary в подпапке, и вы загружаете MergedDictionaries в этот ResourceDictionary. Итак, если в вашем классе Application вы загружаете «my-res-dir / MergedDictionaryLoader.xaml» (по коду или xaml), ВСЕ БУДУЩИЕ ЗАГРУЗКИ MERGEDDICTIONARIES загружаются из «my-res-dir».

Какое-то безумие, если вы спросите меня, я бы подумал, что, поскольку текущий каталог процесса не изменился, вы должны указать "my-res-dir / foo.xaml" для всех ваших дополнительных каталогов. Однако это не так (я не верю, что это где-то задокументировано, по крайней мере, очень хорошо и должно считаться ошибкой, imho).

Так что помните, что загрузка словаря ресурсов WPF будет происходить из каталога, в котором находится текущий XAML . Таким образом, вы указываете Source = "foo.xaml" из вашего "my-res-dir / MergedDictionaryLoader.xaml". Я даже играл с синтаксисом URI pack / absolute, но никогда не находил, что это будет намного более интуитивно понятным.

Старый вопрос, но тем не менее: вам понадобится несколько потоков пользовательского интерфейса - по одному на каждый домен приложения. Создайте их так:

        var thread = new Thread(() =>
        {
            var app = new Application();
            app.Run();
        });
        thread.Name = AppDomain.CurrentDomain.FriendlyName;
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();

Самая большая проблема заключается в том, что вы не можете отправлять FrameworkElements между доменами приложений (они не являются MarshalByRefObject), но вы можете использовать методы FrameworkElementAdapters.ViewToContractAdapter () и ContractAdapterToView (), чтобы обойти это ограничение. Дополнительные сведения см. На странице MSDN FrameworkElementAdapters .

Затем, как только вы это сделаете, самая большая проблема, ИМХО, заключается в том, что вы не можете положить что-либо поверх FrameworkElement из «удаленного» домена (классическая «проблема с воздушным пространством»). См. Эту ветку для получения дополнительной информации об этом.