Общие вспомогательные библиотеки и MEF - PullRequest
0 голосов
/ 31 августа 2018

Я пытаюсь сделать приложение на основе плагинов в C #. Прямо сейчас плагины используют MEF для обнаружения. У меня проблема с различными версиями общих библиотек, используемых хост-приложением и плагином.

На высоком уровне я хочу n + 1 каталогов, один для хоста, n для плагинов, со всеми файлами, которые нужны плагинам или хосту внутри их собственных папок.

У меня есть два решения: одно - MEF Interface, Shared Library и Plugin Host. Второй - это интерфейс MEF, общая библиотека и реализация плагинов.

Это упрощенное представление моей проблемы, демонстрирующее поведение:

Если я изменяю сигнатуру функции ShowMessage в проекте Shared Library, а затем перестраиваю только решение «Реализация плагина», я получаю исключение при вызове PrintInfo. Мне нужен способ, чтобы на хосте плагинов была загружена одна версия, а в реализации плагинов могла быть вторая.

MEF Interface Project

using System.ComponentModel.Composition;

namespace TestProject
{
    [InheritedExport(typeof(IPlugin))]
    public interface IPlugin
    {
        string Name { get; }

        void PrintInfo();
    }
}

Общая библиотека

using System.Windows.Forms;

namespace TestProject
{
    public class SharedLibrary
    {
#if true
        public static void ShowMessage(string message)
        {
            MessageBox.Show(message);
        }
#else
        public static void ShowMessage(string[] message)
        {
            string msg = String.Join("\n", message);
            MessageBox.Show(msg);
        }
#endif
    }
}

Плагин Host

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.Windows.Forms;

namespace TestProject
{
    public partial class Form1 : Form
    {
        [ImportMany(typeof(IPlugin), AllowRecomposition = true)]
        List<IPlugin> allPlugins { get; set; }

        SharedLibrary sl = new SharedLibrary();

        public Form1()
        {
            InitializeComponent();

            AggregateCatalog catalog = new AggregateCatalog();
            DirectoryCatalog pluginDir = new DirectoryCatalog(@"..\..\..\Plugin\bin\Debug");
            catalog.Catalogs.Add(pluginDir);
            CompositionContainer container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string ver = Assembly.GetAssembly(sl.GetType()).GetName().Version.ToString();
            MessageBox.Show("Presenter version = " + ver);

            foreach (var plugin in allPlugins)
            {
                SharedLibrary.ShowMessage("Starting Plugin: " + plugin.Name);
                // this explodes when the shared library in the plugin directory doesn't match
                plugin.PrintInfo();
            }
        }
    }
}

Реализация плагина

using System.Reflection;
using System.Windows.Forms;

namespace TestProject
{
    public class Plugin : IPlugin
    {
        public string Name { get; } = "Test Plugin";

        SharedLibrary sl = new SharedLibrary();

        public void PrintInfo()
        {
            string ver = Assembly.GetAssembly(sl.GetType()).GetName().Version.ToString();
            MessageBox.Show("Plugin version = " + ver);
#if true
            SharedLibrary.ShowMessage("I am a plugin" + "\n" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
#else
            SharedLibrary.ShowMessage(new string[] { "I am a plugin", Assembly.GetExecutingAssembly().GetName().Version.ToString() });
#endif
        }
    }
}
...