.Net 6 Hangfire с динамически загружаемыми плагинами через пользовательскую проблему Type Resolver
Эта проблема связана с тем, что выполнение задания не работает в динамически загружаемых сборках . Мои задания — это dll, которые копируются в plugin\Myplugin1 , plugin\MyPlugin2 и так далее. У каждого плагина есть метод инициализации, который добавляет его типы в DI, поэтому все плагины регистрируют свои типы самостоятельно. Я использую McMaster.NETCore.Plugins nuget для правильной загрузки плагинов с его зависимостями.
Сервер Hangfire работает как консольная служба .Net 6. После настройки Hangfire для разрешения заданий в каталогах плагинов у меня есть ниже простого преобразователя типов
try
{
//first use default resolver. if not try to load from plugin.
var foundType = TypeHelper.DefaultTypeResolver(name);
return foundType;
}
catch (Exception)
{
var asm = Assembly.LoadFrom("[pluginpath]\\Plugin.dll");
return asm.GetType(name)
}
Сначала я статически связал свою DLL-файл задания с проектом Hangfire и установил задание, которое было сохранено в базе данных с приведенной ниже информацией (ниже без данных параметров).
"{""Type"":""MyPlugin.Messaging.IMessageSender`1[[MyPlugin.Messaging.Email.EMailMessage, MyPlugin.Messaging]], MyPlugin.Messaging"",""Method"":""SendAsync"",""ParameterTypes"":""[\""MyPlugin.Messaging.Email.EMailMessage, MyPlugin.Messaging\""]""
С этой сериализованной информацией, когда Hangfire пытается разрешить типы, она дважды приходит к моему пользовательскому преобразователю.
- 1-й тип для разрешения: MyPlugin.Messaging.IMessageSender`1[[MyPlugin.Messaging.Email.EMailMessage, MyPlugin.Messaging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], MyPlugin.Messaging, Version=1.0. 0.0, культура = нейтральная, PublicKeyToken=null
- Второй тип для разрешения: MyPlugin.Messaging.Email.EMailMessage, MyPlugin.Messaging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
В обоих вышеперечисленных случаях DefaultTypeResolver правильно разрешает типы, поскольку эта dll напрямую связана с серверным проектом, и задание выполняется правильно.
Затем я удалил прямую ссылку на свой плагин и запустил сервер, поместив plugin.dll в папку с плагинами. Когда я ставлю задачу; та же информация о задании сохраняется в БД правильно. Затем он дважды попадает, чтобы разрешить типы. Теперь DefaultResolver не может найти тип, поэтому он переходит к исключению, когда я загружаю dll из пути плагина и пытаюсь вернуть тип.
Вот в чем проблема, которую я не понимаю. Когда плагин напрямую связан с серверным проектом; TypeHelper.DefaultTypeResolver([строка имени типа]); правильно найти тип, но когда он не связан напрямую; Assembly.LoadFrom(...) & GetType([строка имени типа]) возвращает значение null.
Итак, если я перечисляю все типы в загруженной сборке, она дает все имена классов, но не перечисляет тип MyPlugin.Messaging.IMessageSender`1[[MyPlugin.Messaging.Email.EMailMessage, MyPlugin.Messaging, Version=1.0.0.0, культура = нейтральная, PublicKeyToken=null]], MyPlugin.Messaging, версия =1.0.0.0, культура = нейтральная, PublicKeyToken=null
Однако инициализированный код моего плагина устанавливает его типы в DI, как показано ниже, что, по-видимому, сериализуется в базу данных Hangfire.
services.TryAddTransient<IMessageSender<EMailMessage>, EMailMessageSender>();
Меня смущает то, как вышеприведенный тип разрешается DefaultResolver, когда dll жестко привязан к серверному проекту и терпит неудачу при динамической загрузке? Я убедился, что
В чем может быть проблема?