Внедрение зависимостей с загруженной сборкой во время выполнения - PullRequest
0 голосов
/ 13 марта 2020

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

public static void Main(string[] args)
{
    var services = new ServiceCollection();
    services.AddLogging();
    services.AddSingleton<IDemo, Demo>();
    Provider = services.BuildServiceProvider();

    Console.WriteLine("ok");
}

В этом приложении есть папка надстройки. и при запуске он загружает все надстройки, доступные в папке, например:

private static IEnumerable<Type> LoadAddin()
{
var basePath = $@"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}\addin";

var dir = new DirectoryInfo(basePath);
if (!dir.Exists)
    dir.Create();

var addins = new List<Type>();

//Loop over all subfolder in the Addin folder
foreach (var subDirectory in dir.GetDirectories())
{
    //Loop over all file
    foreach (var file in subDirectory.GetFiles())
    {
        try
        {
            //load assembly
            var myDll = Assembly.LoadFrom(file.FullName);
            var types = myDll.GetExportedTypes();

            //Check if any type inside the dll match IExt
            foreach (var type in types)
            {
                if (type.GetInterface(nameof(IExt)) == null) continue;
                    addins.Add(type);
            }
        }
        catch (Exception e)
        {
            // ignored
        }
    }
}

, после этого я правильно получаю все надстройки. У каждого дополнения есть метод запуска для загрузки определенных c сервисов, и все они совместно используют общий сервис "IDemo".

public IAddin Start(IServiceCollection services)
{
    services.AddLogging();
    services.AddSingleton<IAddin, Test>();

    var provider = services.BuildServiceProvider();

    return provider.GetService<IAddin>();
}

, и мой основной теперь:

public static void Main(string[] args)
{
    var services = new ServiceCollection();
    services.AddLogging();
    services.AddSingleton<IDemo, Demo>();
    Provider = services.BuildServiceProvider();
    var addins = LoadAddin();
    foreach (var ext in addins)
    {
        var t = (IExt)ActivatorUtilities.CreateInstance(Provider, ext);
        t.Start(services);
    }
    Console.WriteLine("ok");
}

и вот проблема. Я получил это исключение:

System.MissingMethodException: Method not found: 'Microsoft.Extensions.DependencyInjection.IServiceCollection Microsoft.Extensions.DependencyInjection.LoggingServiceCollectionExtensions.AddLogging(Microsoft.Extensions.DependencyInjection.IServiceCollection)'.
  at Ext.Init.Start(IServiceCollection services)
  at ConsoleApplication1.Program.Main(String[] args) dans **\Program.cs:ligne 25

Если я добавляю ссылку на свой проект и добавляю ее без ActivatorUtilities, она работает, но мне нужно иметь возможность загрузить ее на лету. И я не могу найти подвох. Единственное решение, которое я нашел, это удалить AddLogging из моего аддина, но это не настоящее решение, потому что мне все еще нужен ILogger в аддине.

Есть идеи?

РЕДАКТИРОВАТЬ Вот папка sln

...