Сведения о вопросе

NOTtoday

14:10, 18th August, 2020

Теги

Как загрузить плагины в .NET?

Просмотров: 477   Ответов: 7

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

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



  Сведения об ответе

PROGA

08:27, 17th August, 2020

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


  Сведения об ответе

ASSembler

13:52, 11th August, 2020

Следующий фрагмент кода (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);
        }
    }
}

Edit: классы, на которые ссылается Мэтт , вероятно, являются лучшим вариантом в .NET 3.5.


  Сведения об ответе

$DOLLAR

05:43, 27th August, 2020

Динамическая загрузка плагинов

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

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 при разгрузке AppDomains .

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

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

Существующие платформы плагинов

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

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


  Сведения об ответе

$DOLLAR

12:41, 4th August, 2020

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

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

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

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

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

AppDomain.Unload(domain);


  Сведения об ответе

$DOLLAR

06:18, 24th August, 2020

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


  Сведения об ответе

crush

17:59, 8th August, 2020

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

Первый-импортировать 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-способ: с помощью отражения. Проверьте пространство имен System.Reflection и следующие методы:

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


  Сведения об ответе

repe

16:21, 19th August, 2020

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться