Загрузите сборку без блокировки файла И сохраните правильный контекст привязки - PullRequest
7 голосов
/ 11 марта 2011

Я противостою грозной головоломке.Вот моя ситуация:

Я создаю приложение с помощью инфраструктуры плагинов.Существует базовый класс плагинов, который должны расширяться всеми плагинами.В той же сборке у меня есть вспомогательный класс, который сериализует и десериализует классы.Это универсальный класс, и он используется повсеместно.Структура выглядит следующим образом:

MyApp.dll
|_ App.cs
|_ HelperCollection.cs
|_ PluginBase.cs

MyPlugin.dll
|_MyPlugin.cs (this extends PluginBase)
|_Foo.cs

Проблема

Моя проблема заключается в загрузке и блокировке файлов сборки.Требование приложения заключается в том, что Плагины могут быть перезаписаны в любое время.Если это так, их необходимо перезагрузить.Кажется, лучший способ загрузить сборку, чтобы она не была заблокирована (то есть я могу перезаписать ее или удалить, пока приложение еще работает), это:

byte[] readAllBytes = File.ReadAllBytes("MyPlugin.dll");
Assembly assembly = Assembly.Load(readAllBytes);

Загрузка сборки плагина работает простохорошо, никаких проблем нет.Я получаю исключение, когда из MyPlugin.cs , который находится в сборке плагина, я пытался использовать HelperCollection для десериализации.Примером может быть что-то вроде этого:

// HelperCollection uses XmlSerializer under the covers
List<Foo> settingCollection = HelperCollection<Foo>.Deserialize("mysettings.xml");

Он взрывается и выбрасывает InvalidCastException, говоря, что это "Unable to cast object of type 'List[Foo]' to 'List[Foo]'".После долгих исследований я наконец нашел причину .Он загружается в контексте привязки LoadNeither .

Когда загружено Foo (из MyPlugin.dll ), оно находится в контексте привязки LoadNeither, тогда как сборка, содержащая тип для преобразования типа (в моем случае, )MyApp.dll ) загружается в контексте по умолчанию.Таким образом, даже если они имеют одинаковое имя, они не считаются одним и тем же типом.Он делает это, потому что я использую Assembly.Load(byte[]).

Вопросы

Как я могу обойти это?Как можно,

  1. загрузить сборку и не блокировать файл, и
  2. предоставить правильный контекст привязки, чтобы я мог приводить объекты, находящиеся в загруженной сборке.

Извините за стену текста, просто хотел получить всю необходимую информацию там.

Ответы [ 2 ]

6 голосов
/ 11 марта 2011

Вы пробовали теневое копирование ?

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

2 голосов
/ 11 марта 2011

Просто идея из головы:

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

Когда пользователь удаляет новые плагины, вы убиваете домен приложения плагинов и перезагружаете их.

Просто идея.

...