Рабочее приложение .Net Core 3 с плагинами с конструктором с параметрами - PullRequest
1 голос
/ 01 ноября 2019

Я создаю службу Windows с перезагружаемыми плагинами, используя .Net Core 3. Я начал с шаблона проекта Worker Service и добавил функцию плагинов, используя рекомендации в статье Microsoft Создание приложения .NET Core с плагинами . Мои плагины используют внешние зависимости, и все загружается нормально. Кроме того, мое решение может загружать / выгружать плагины без перезапуска службы, и пока все работает нормально. Теперь я хочу добавить параметры в конструктор плагинов (в данный момент конструктор плагинов меньше параметров), которые будут разрешены DI из службы, но безуспешно. Мне нужно пройти ex. ILogerFactory, DbContext для плагина с помощью инжектора конструктора.

Для создания экземпляра плагина я использую

ActivatorUtilities.CreateInstance(this._serviceProvider, pluginType)

this._serviceProvider - это параметр конструктора в методе, из которого создаются плагины, и он правильно разрешениз DI:

public TransformFile(ILogger<TransformFile> logger, IConfiguration configuration, IServiceProvider serviceProvider)

Если у меня есть такой конструктор плагинов

public TransformationPlugin(ILoggerFactory loggerFactory)

Исключение выдается

Unable to resolve service for type 'Microsoft.Extensions.Logging.ILoggerFactory' while attempting to activate 'Transformation.TransformationPlugin'.

Если у меня есть конструктор плагинов, подобный этому

public TransformationPlugin(IServiceProvider serviceProvider)

Я получаю serviceProvider с 45 зарегистрированными службами, но GetService возвращает значение NULL для каждой службы. Если я остановлю выполнение в конструкторе плагинов в Immediate Window, я смогу решить ex. ILoggerFactory. Я пытаюсь как с

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

, так и без него в плагине .csproj, но результат одинаков. Также в плагинах .csproj у меня есть <Private>false</Private> для проекта, в котором определен интерфейс.

1 Ответ

0 голосов
/ 10 ноября 2019

Я нашел решение. Из документации было ясно, что для двух типов, которые должны рассматриваться как одинаковые, они должны быть загружены из одной и той же сборки. Я ошибочно полагал, что сборки Microsoft. * И Systems. * Будут загружаться так же, как загруженный общий проект. После некоторого исследования я обнаружил, что эти сборки в основной программе загружаются из папки bin, но в плагине они загружаются из C: \ Users \ username \ .nuget \ packages ... Причина заключается в том, как работает AssemblyDependencyResolver. ,Поэтому в PluginAssemblyLoadContext в методе переопределенной загрузки я заменил

string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
        if (assemblyPath != null)
        {
            return LoadFromAssemblyPath(assemblyPath);
        }

на

if (!assemblyName.FullName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase) && !assemblyName.FullName.StartsWith("System", StringComparison.OrdinalIgnoreCase))
        {
            string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
            if (assemblyPath != null)
            {
                return this.LoadFromFile(assemblyPath);
            }
        }

, и теперь и в основной программе, и в плагине Microsoft. * И System. * Сборки совместно используются и типы (ILoggerFactory), IConfiguration, ...) считаются одинаковыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...