Хорошая архитектура / библиотека для надежного управления плагинами / надстройками - PullRequest
7 голосов
/ 31 марта 2011

У нас есть приложение, которое, как одно из его требований, будет принимать произвольные сторонние плагины, загружать их и запускать их пользовательский интерфейс вместе с нашим собственным приложением.Мы загружали эти сторонние плагины в свои собственные домены приложений в целях изоляции, и все работает нормально.

Пока не произойдет сбой одного из плагинов с необработанным исключением.В этом случае все приложение отключается, хотя все, что действительно затронуто, - это одно из наших «дополнительных» окон инструментов.

Мы хотели бы, в идеале, каким-то образом обработать «необработанное» исключение, выгрузить поврежденный AppDomain, а затем просто перезагрузить его заново. Проблема в том, что мы не можем найтимеханизм в обработчике событий для необработанного исключения, посредством которого мы можем пометить исключение как «обработанное».Кроме того, поскольку плагины имеют свои собственные компоненты пользовательского интерфейса со своим собственным набором взаимодействий с пользователем, было бы чрезвычайно трудно «обернуть» наши взаимодействия с плагинами в блоки try / catch / finally.

Существуют ли какие-либо фреймворки / библиотеки / шаблоны программирования, пригодные для решения этой проблемы?Мы можем сделать плагин хорошо; нам нужна помощь в поддержании работы приложения, когда код в другом домене приложений неожиданно завершается с ошибкой.

Ответы [ 5 ]

9 голосов
/ 03 апреля 2011

Вы можете использовать System.Addin framework (иногда известный как MAF), который немного затрудняет правильную настройку, но который был разработан для обеспечения изоляции (защита от сбоев).System.Addin основан на удаленном взаимодействии.С помощью этой среды вы можете позволить плагинам запускаться с ограниченными разрешениями в том же процессе, или в другом домене приложения, или даже в другом процессе.вариант.Однако это может привести к снижению производительности.

Этот код можно использовать для загрузки надстройки в другом домене приложения:

AppDomain addInDomain = AppDomain.CreateDomain("addin domain");

// addInDomain.PermissionSet = ...
AddInEnvironment env = new AddInEnvironment(addInDomain);

// Activate the add-in
IHostView addinInstance = addinToken.Activate<IHostView>(env);

Console.WriteLine(addinInstance.DoSomething());

AppDomain.Unload(addInDomain);

Если вы хотите загрузить надстройку в другой процесс, для полной изоляции:

AddInProcess process = new AddInProcess();
process.Start();

// Activate the add-in
IHostView addinInstance = addinToken.Activate<IHostView>(process, AddInSecurityLevel.Internet);

try 
{
    // use a catch block, prevent exceptions from the addin crashing the main app
    Console.WriteLine(addinInstance.DoSomething());
} 
catch (Exception e)
{
    Console.WriteLine(e);
}

process.Shutdown();

Этот блог дает хорошее описание настройки этого параметра.

Возможно объединить System.Addin с MEF, этодополнительные наборы инструментов, см. эту статью .

Обратите внимание, что модель System.Addin может обеспечивать защиту от сбоев, вам все равно придется иметь дело с замедлениями или взаимоблокировками в коде надстройки.Здесь поможет асинхронное использование.

1 голос
/ 07 апреля 2011

Я не думаю, что это возможно. Насколько я понимаю, что даже если вы обработаете событие AppDomain.UnhandledException , приложение все равно прекратит работу. Лучшее, что вы можете сделать, - это обработать исключение, записать то, что вы можете, сохранить то состояние, в котором вы можете, и завершить работу корректно.

1 голос
/ 31 марта 2011
1 голос
/ 31 марта 2011

Звучит так, будто вы хотите что-то похожее на OSGi для Java - Является ли MEF OSGi для .NET? похоже, что оно может соответствовать всем требованиям.

0 голосов
/ 08 апреля 2011

Я предполагаю, что вы уже проверили документацию, но если нет, то на следующей странице

http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

предоставляет много информации о том, как работают необработанные исключения.В нем также упоминается несколько атрибутов, которые позволяют точно настроить поведение.

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

...