Как загрузить плагины в .NET? - PullRequest
26 голосов
/ 18 августа 2008

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

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

Ответы [ 7 ]

28 голосов
/ 18 августа 2008

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

20 голосов
/ 18 августа 2008

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

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

8 голосов
/ 06 января 2013

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

Для получения информации о том, как динамически загружать сборки .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) для создания инфраструктуры подключаемых модулей.

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

Я знаю о двух плагинах:

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

5 голосов
/ 18 августа 2008

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

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

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

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

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

AppDomain.Unload(domain);
4 голосов
/ 10 сентября 2008

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

3 голосов
/ 18 августа 2008

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

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

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

2 голосов
/ 18 августа 2008

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

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

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