Как загрузить компонент MEF из другой сборки в .net core 2.1 - PullRequest
0 голосов
/ 01 ноября 2018

Я просто делаю первые шаги на территории MEF и хотел сделать это, используя .net core 2.1.

Использование VS 2017 (версия 15.8.8) Я создал небольшое консольное приложение (.NET Core) с интерфейсом

interface IMessageSender
{
    void Send(string message);
}

и реализация (в том же проекте)

[Export(typeof(IMessageSender))]
public class EmailSender : IMessageSender
{
    public void Send(string message)
    {
        Console.WriteLine("EmailSender : " + message);
    }
}

Наконец, у меня есть небольшой метод compose, выполненный из моего Main (string [] args)

    [Import]
    private void Compose()
    {
        var assembly_A = new[] { typeof(Program).GetTypeInfo().Assembly };
        var config_A = new ContainerConfiguration().WithAssembly(assembly_A[0]);
        var container_A = config_A.CreateContainer();
        var msg_A = container_A.GetExport<IMessageSender>();
        msg_A.Send("Hello");
    }

Работает как положено

enter image description here

Однако, если я добавлю новую библиотеку классов в свое решение и перенесу свою реализацию Send (string) во вновь добавленный проект, все не получится.

namespace AnotherMefExtensionProjectNamespace
{
  [Export(typeof(IMessageSender))]
  public class EmailSenderExtended : IMessageSender
  {
    public void Send(string message)
    {
        Console.WriteLine("EmailSenderExtended : " + message);
    }
  }
}

Новый метод Compose

    [Import]
    public IMessageSender MessageSender { get; set; }
    private void Compose()
    {
        var assembly_B = new[] { typeof(EmailSenderExtended).GetTypeInfo().Assembly };
        var config_B = new ContainerConfiguration().WithAssembly(assembly_B[0]);
        var container_B = config_B.CreateContainer();
        var msg_B = container_B.GetExport<IMessageSender>();
        msg_B.Send("Hello");
    }

enter image description here

Я пытался сравнить разные конфиги и контейнеры (_A против _B в примерах), но не могу понять, в чем отличие. Я даже пытался расширить класс ContainerConfiguration для загрузки из указанной сборки, и он работает до тех пор, пока данный файл содержит метод Main, но не работает, если я использую свою «расширенную» библиотеку базовых классов .NET.

        public static ContainerConfiguration WithChosenAssembly(this ContainerConfiguration configuration, string pathAndFile)
    {
        var context = AssemblyLoadContext.Default.LoadFromAssemblyPath(pathAndFile);
        var ass_list = new List<Assembly>() { context };
        configuration = configuration.WithAssemblies(ass_list, null);
        return configuration;
    }

У меня сложилось впечатление, что вы расширяете свое основное приложение, разрабатывая библиотеку классов, которая в основном реализует указанные интерфейсы. Кажется, я сейчас не могу этого сделать, но, очевидно, я неправильно понял что-то очень простое.

Если кто-то захочет поставить меня на правильный путь или дать альтернативную идею для разработки плагинов для ядра .net, я был бы очень признателен.

С уважением Magnus

1 Ответ

0 голосов
/ 02 ноября 2018

Я понял, что моя тестовая установка не имитирует сценарий реального мира, и поэтому я навлек на себя свои проблемы.

Очевидно, у меня должно было быть три проекта.

  1. Один проект только с определениями интерфейса.
  2. Один "главный" проект, в котором существует весь мой обычный код.
  3. Один (или несколько) проектов, в которых существуют мои реализации интерфейсов MEF.

Рассматривая мой пример и придерживаясь очевидного «замысла» над всем, все работает именно так, как и должно. Большинство пользователей StackOverflow, вероятно, не сделали бы мою ошибку, но для тех, кто сделал, я надеюсь, что вышеупомянутое помогает. : -)

...