Вопрос

Я хотел бы предоставить какой-нибудь способ создания динамически загружаемых плагинов в моем программном обеспечении.Типичный способ сделать это - использовать Загружаемая библиотека Функция WinAPI для загрузки библиотеки dll и вызова Получитьprocaddress чтобы получить указатель на функцию внутри этой библиотеки dll.

Мой вопрос заключается в том, как мне динамически загружать плагин в приложение C # / .Net?

Это было полезно?

Решение

Следующий фрагмент кода (C #) создает экземпляр любых конкретных классов, производных от Base находится в библиотеках классов (* .dll) в пути к приложению и сохраняет их в виде списка.

using System.IO;
using System.Reflection;

List<Base> objects = new List<Base>();
DirectoryInfo dir = new DirectoryInfo(Application.StartupPath);

foreach (FileInfo file in dir.GetFiles("*.dll"))
{
    Assembly assembly = Assembly.LoadFrom(file.FullName);
    foreach (Type type in assembly.GetTypes())
    {
        if (type.IsSubclassOf(typeof(Base)) && type.IsAbstract == false)
        {
            Base b = type.InvokeMember(null,
                                       BindingFlags.CreateInstance,
                                       null, null, null) as Base;
            objects.Add(b);
        }
    }
}

Редактировать: Классы , на которые ссылаются Мэтт вероятно, это лучший вариант в .NET 3.5.

Другие советы

Начиная с .NET 3.5, существует формализованный, встроенный способ создания и загрузки плагинов из приложения .NET.Все дело в Система.Добавление пространство имен.Для получения дополнительной информации вы можете ознакомиться с этой статьей на MSDN: Надстройки и расширяемость

Динамически Загружаемые плагины

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

var domain = AppDomain.CreateDomain("NewDomainName");
var pathToDll = @"C:\myDll.dll"; 
var t = typeof(TypeIWantToLoad);
var runnable = domain.CreateInstanceFromAndUnwrap(pathToDll, t.FullName) 
    as IRunnable;
if (runnable == null) throw new Exception("broke");
runnable.Run();

Выгрузка плагинов

Типичным требованием фреймворка плагинов является выгрузка плагинов.Для выгрузки динамически загружаемых сборок (например,подключаемые модули и надстройки) вы должны выгрузить содержащий AppDomain.Для получения дополнительной информации см. эта статья о MSDN посвящена выгрузке доменов приложений.

Использование WCF

Существует вопрос и ответ о переполнении стека в нем описывается, как использовать Windows Communication Framework (WCF) для создания подключаемого модуля framework.

Существующие фреймворки подключаемых модулей

Я знаю о двух подключаемых фреймворках:

Некоторые люди говорят о Платформа управляемой расширяемости (MEF) как подключаемый модуль или надстройка, которой он не является.Для получения дополнительной информации см. этот StackOverflow.com вопрос и этот StackOverflow.com вопрос.

Один из советов - загрузить все плагины и тому подобное в собственный домен приложения, поскольку запущенный код может быть потенциально вредоносным.Собственный домен приложения также можно использовать для "фильтрации" сборок и типов, которые вы не хотите загружать.

AppDomain domain = AppDomain.CreateDomain("tempDomain");

И загрузить сборку в домен приложения:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
Assembly assembly = domain.Load(assemblyName);

Чтобы выгрузить домен приложения:

AppDomain.Unload(domain);

Да, ++ Мэтту и System.Дополнение (статья в журнале MSDN magazine из двух частей о System.Дополнения доступны здесь и здесь).Другая технология, на которую вы, возможно, захотите взглянуть, чтобы получить представление о том, куда может пойти .NET Framework в будущем, - это Платформа управляемой Расширяемости в настоящее время доступен в форме CTP на Codeplex.

В принципе, вы можете сделать это двумя способами.

Первый - импортировать kernel32.dll и использовать LoadLibrary и GetProcAddress, как вы использовали это раньше:

[DllImport("kernel32.dll")]

internal static extern IntPtr LoadLibrary(String dllname);

[DllImport("kernel32.dll")]

internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);

Второй способ - сделать это .СЕТЕВЫМ способом:используя отражение.Проверьте систему.Пространство имен отражения и следующие методы:

Сначала вы загружаете сборку по ее пути, затем получаете из нее тип (класс) по его имени, затем снова получаете метод класса по его имени и, наконец, вызываете метод с соответствующими параметрами.

Статья немного старше, но все еще применима для создания уровня расширяемости в вашем приложении:

Позвольте пользователям добавлять функциональность в ваши приложения .NET с помощью макросов и подключаемых модулей

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top