Как внедрить плагины .net без использования доменов приложений? - PullRequest
5 голосов
/ 19 января 2009

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

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

Кроме того, домены приложений не работали для меня, потому что мне нужно было передавать тип между доменами в качестве параметра для работы InvokeWorkflow в Speech Server worfklow. К сожалению, отправка типа по доменам приводит к внедрению сборки в локальный домен приложений.

Кроме того, это относится к IIS. В IIS есть параметр «Теневое копирование», позволяющий перезаписывать исполняемую сборку при ее загрузке в память. Проблема заключается в том, что (по крайней мере, под XP, тестирование на серверах производства 2003 не проводилось), когда вы программно загружаете сборку, теневая копия не работает (потому что вы загружаете DLL, а не IIS).

Ответы [ 3 ]

8 голосов
/ 19 января 2009
  1. Проверьте, загружена ли сборка (чтобы избежать утечек памяти, вызванных загрузкой одной и той же сборки снова и снова).
  2. Если он не загружен, считайте сборку в байтовый массив. Это предотвратит блокировку файла.
  3. Предоставить массив байтов в качестве аргумента для Assembly.Load

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

Assembly assembly = null;

foreach(Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
    if (loadedAssembly.FullName == "foobar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
        assembly = loadedAssembly;

if(assembly == null)
{
    byte[] studybin = System.IO.File.ReadAllBytes(@"C:\pathToAssembly\foobar.dll");
    assembly = Assembly.Load(studybin);                
}

Обратите внимание, что если вы пытаетесь найти определенную сборку в каталоге, вы можете запустить 'System.Reflection.AssemblyName.GetAssemblyName (path);' чтобы увидеть, соответствует ли FullName тому, что вы ищете. GetAssemblyName (путь) НЕ внедряет сборку в ваш текущий домен приложений.

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

2 голосов
/ 20 июля 2009

Если вас интересует серьезный метод построения системы с архитектурой плагинов, вы можете попробовать MAF (Managed Add-in Framework), который теперь является частью .NET Framework, а именно System.AddIn Пространство имен.

Это поможет вам управлять изоляцией надстроек и управлением версиями, даже обратной совместимостью с контрактами.

Здесь есть некоторая кривая обучения, так что это может быть не совсем то, что вы ищете.

http://msdn.microsoft.com/en-us/library/bb384200.aspx

2 голосов
/ 20 июля 2009

Если вы хотите изолировать свои надстройки, вы должны ...

  1. Создайте тип, который расширяет MarshallByRefObject, который будет взаимодействовать с вашими надстройками (давайте позвоним это FOOMASTER)
  2. Создайте новый домен приложения (давайте назовем его addinLand)
  3. Вызов addinLand.CreateInstanceAndUnwrap to создать экземпляр FOOMASTER в addinLand и получить прокси в текущий домен приложения
  4. Скажите FOOMASTER, чтобы загрузить ваши дополнения

Теперь ваши надстройки загружаются в addinLand, и вы можете взаимодействовать с ними из основного домена приложения через прокси-сервер FOOMASTER. Когда ваши надстройки рушатся, они не удаляют ваше приложение.

Это интересный и немного запутанный процесс. Первоначально я думал, что идея состоит в том, чтобы загрузить ваши надстройки и затем перенести их в текущий домен приложения в качестве прозрачных прокси, но лучший дизайн - оставить надстройки в виде простых объектов, которые взаимодействуют с более сложными типами, которые вы создаете (FOOMASTER), которые расширяют MarshallByRefObject, которые загружаются в домен приложения addinLand и с прозрачными прокси которых вы взаимодействуете.

Главы 21 и 22 CLR Via C # очень полезны для понимания процесса.

...