1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/hyjiacan-Plugin.NET

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Plugin.NET

Цель Plugin.NET — создание гибкого менеджера плагинов на C#. Менеджер использует технологию рефлексии для динамической загрузки DLL-библиотек (плагины). При использовании менеджера требуется передать абстрактный класс в качестве параметра типа, а плагины должны реализовать этот интерфейс. Приложение затем вызывает методы этого интерфейса для взаимодействия с плагинами.

Проект активно развивается в свободное время после работы, поэтому прогресс может быть медленным. Добро пожаловать к участию в PR! :relieved: :relieved: :relieved:

Операционная среда

Проект написан на .NET Framework Yöntem 4.0, но можно легко адаптировать его для использования с .NET 2.0 и .NET Core.

Определение интерфейсов

Интерфейсы представляют собой абстрактные классы, содержащие обязательные и необязательные методы. Обязательные методы помечаются как abstract, а необязательные — как virtual. Пример ниже:

/// <summary>
/// Интерфейс плагина
/// </summary>
public abstract class PluginInterface
{
    /// <summary>
    /// Название плагина
    /// </summary>
    public abstract string Name { get; }

    /// <summary>
    /// Версия плагина
    /// </summary>
    public abstract Version Version { get; }

    /// <summary>
    /// Описание плагина
    /// </summary>
    public virtual string Description { get; }

    /// <summary>
    /// Вызывается при загрузке плагина, обязательно должно быть реализовано
    /// </summary>
    public abstract void Load();

    /// <summary>
    /// Первый метод функциональности, необязательный метод
    /// </summary>
    /// <returns></returns>
    public virtual string Method1()
    {
        return null;
    }

    /// <summary>
    /// Второй метод функциональности, необязательный метод
    /// </summary>
    /// <param name="from"></param>
    /// <returns></returns>
    public virtual string Method2(string from)
    {
        return from;
    }
}

Использование virtual позволяет удобно обновлять интерфейсы без необходимости изменения всех плагинов.

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

Проект плагина должен ссылаться на библиотеку с интерфейсом. При выпуске плагина библиотека интерфейса не должна выпускаться, но все остальные зависимости должны быть включены. Менеджер будет искать классы, наследующие интерфейс, и создаст экземпляр первого найденного класса без параметров.

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

Процесс использования менеджера плагинов

  1. Создайте класс интерфейса для вашего приложения и импортируйте его в основной проект.
  2. Импортируйте библиотеку Plugin.NET.dll.
  3. Инициализируйте менеджер плагинов.
  4. Привяжите события менеджера плагинов, предоставляющие данные о процессах загрузки.
  5. Вызовите метод Load(), чтобы загрузить все существующие плагины, возможно, передав функцию-фильтр.
  6. Для возможности горячей загрузки плагинов вызовите метод Watch() для мониторинга новых плагинов в директории.
  7. Чтобы прекратить горячую загрузку, вызовите метод StopWatch().

Пример

class Program
{
    static void Main(string[] args)
    {
        // Используйте интерфейс для создания экземпляра менеджера плагинов
        // Если вам нужны другие интерфейсы, вы можете создать еще один экземпляр менеджера плагинов
        var pluginManager = new PluginManager<PluginInterface>();

        // Обрабатывайте события, отправляемые менеджером плагинов
        pluginManager.OnAssemblyLoading += PluginManager_OnAssemblyLoading;
        pluginManager.OnAssemblyLoaded += PluginManager_OnAssemblyLoaded;
        pluginManager.OnError += PluginManager_OnError;
        pluginManager.OnInstanceCreating += PluginManager_OnInstanceCreating;
        pluginManager.OnInstanceCreated += PluginManager_OnInstanceCreated;

        // Загружаем все плагины в директории
        pluginManager.Load();

        // Начинаем мониторить новые плагины, добавленные в директорию
        pluginManager.Watch();

        Console.WriteLine("Мониторинг изменений в директории плагинов, нажмите Enter для выхода");
        Console.ReadLine();
    }

    private static void PluginManager_OnAssemblyLoading(object sender, PluginAssemblyLoadingArgs e)
    {
        Console.WriteLine($"Подготовка к загрузке сборки из файла \"{e.FileName}\"");
    }

    private static void PluginManager_OnAssemblyLoaded(object sender, PluginAssemblyLoadedArgs e)
    {
        Console.WriteLine($"Успешная загрузка сборки из файла \"{e.FileName}\": \"{e.Assembly}\"");
    }

    private static void PluginManager_OnInstanceCreating(object sender, PluginInstanceCreatingArgs e)
    {
        Console.WriteLine($"Подготовка к загрузке типа \"{e.Class}\" из сборки \"{e.Assembly}\"");
    }

    private static void PluginManager_OnInstanceCreated(object sender, PluginInstanceCreatedArgs<PluginInterface> e)
    {
        var plugin = e.Instance;
        Console.WriteLine($"Успешная загрузка типа \"{e.Class}\" из сборки \"{e.Assembly}\"");
        Console.WriteLine($"Название плагина: {plugin.Name}, версия: {plugin.Version}");
        e.Instance.Load();
        Console.WriteLine("Method1:" + plugin.Method1());
        Console.WriteLine("Method2:" + plugin.Method2("啊呀哟"));
    }

    private static void PluginManager_OnError(object sender, PluginErrorEventArgs e)
    {
        switch (e.ErrorType)
        {
            case PluginNET.error.PluginErrorTypes.None:
                break;
            case PluginNET.error.PluginErrorTypes.InvalidDll:
                Console.WriteLine($"Файл \"{e.FileName}\" не является действительной DLL: {e.Exception}");
                break;
            case PluginNET.error.PluginErrorTypes.CannotLoadClassTypes:
                Console.WriteLine($"Не удалось загрузить типы из файла \"{e.FileName}\"");
                break;
            case PluginNET.error.PluginErrorTypes.ImplementionClassNotFound:
                Console.WriteLine($"В файле \"{e.FileName}\" не найдено ни одного класса, реализующего указанный интерфейс");
                break;
            case PluginNET.error.PluginErrorTypes.IllegalClassDefinition:
                Console.WriteLine($"В файле \"{e.FileName}\" найден класс, реализующий указанный интерфейс, но он не объявлен как класс или объявлен как абстрактный или не является публичным");
                break;
            case PluginNET.error.PluginErrorTypes.DefaultConstructorNotFound:
                Console.WriteLine($"В файле \"{e.FileName}\" найден класс, реализующий указанный интерфейс, но не найден конструктор без параметров");
                break;
            case PluginNET.error.PluginErrorTypes.InstanceCreateFailed:
                Console.WriteLine($"В файле \"{e.FileName}\" найден класс, реализующий указанный интерфейс \"{e.ClassType}\", но возникло исключение при создании экземпляра: {e.Exception}");
                break;
            case PluginNET.error.PluginErrorTypes.Unknown:
                Console.WriteLine("Неизвестная ошибка");
                break;
            default:
                break;
        }
    }
}

Примеры можно найти в каталоге test решения, тестовый проект — Plugin.NETTest.

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

C# плагин-менеджер. Развернуть Свернуть
MIT
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/hyjiacan-Plugin.NET.git
git@api.gitlife.ru:oschina-mirror/hyjiacan-Plugin.NET.git
oschina-mirror
hyjiacan-Plugin.NET
hyjiacan-Plugin.NET
master