Как ссылаться на DLL во время выполнения? - PullRequest
8 голосов
/ 22 апреля 2011

Я создаю приложение с WPF и C #, в основном я хочу позволить любому создать dll и поместить его в папку (аналогично плагинам).Приложение возьмет все библиотеки DLL в папке, загрузит их и использует их методы (определенные в интерфейсе).

Есть идеи, как ссылаться на библиотеки DLL во время выполнения?Есть идеи лучше, как это реализовать?

Ответы [ 6 ]

10 голосов
/ 22 апреля 2011

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

public class PlugInFactory<T>
{
    public T CreatePlugin(string path)
    {
        foreach (string file in Directory.GetFiles(path, "*.dll"))
        {
            foreach (Type assemblyType in Assembly.LoadFrom(file).GetTypes())
            {
                Type interfaceType = assemblyType.GetInterface(typeof(T).FullName);

                if (interfaceType != null)
                {
                    return (T)Activator.CreateInstance(assemblyType);
                }
            }
        }

        return default(T);
    }
}

Все, что вам нужно сделать, это инициализировать этот класс примерно так:


   PlugInFactory<InterfaceToSearchFor> loader = new PlugInFactory<InterfaceToSearchFor>();
     InterfaceToSearchFor instanceOfInterface = loader.CreatePlugin(AppDomain.CurrentDomain.BaseDirectory);

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

1 голос
/ 22 апреля 2011

Я думаю, вы можете начать с чего-то вроде

Assembly assembly = Assembly.LoadFrom("Something.dll");
Type type = assembly.GetType("SomeType");
object instanceOfSomeType = Activator.CreateInstance(type);

Тогда вы можете использовать это

1 голос
/ 22 апреля 2011

Посмотрите на MEF .он должен предоставить именно то, что вы ищете.

Использование отражение также вариант, но MEF будет лучшим выбором, если вы спросите меня.

0 голосов
/ 30 января 2019

Ответы выше в значительной степени дают вам то, что вам нужно. Вы можете попытаться загрузить все dll, которые будут подключены к вашему приложению при запуске программы:

// note: your path may differ, this one assumes plugins directory where exe is executed
var pluginsDirectory = Path.Combine(AppContext.BaseDirectory, "plugins");
if (Directory.Exists(pluginsDirectory))
{
    var dllPaths = Directory.GetFiles(pluginsDirectory);
    if (dllPaths.Count() > 0)
    {
        foreach (var dllPath in dllPaths)
        {
            Assembly.LoadFrom(Path.Combine("plugins", Path.GetFileName(dllPath)));
        }
    }
    else
    {
        // warn about no dlls
    }
}
else
{
    // warn about no plugins directory
}

Как ссылаться на dll и ее типы:

// if dll file name is My.Plugin.Assembly.ShortName.dll, then reference as follows
var pluginAssembly = Assembly.Load("My.Plugin.Assembly.ShortName");
var typesInAssembly = pluginAssembly.GetExportedTypes();
var instanceType = typesInAssembly.FirstOrDefault(t => t.Name == "MyClassName");
var instance = Activator.CreateInstance(instanceType, new object[] { "constructorParam1", "constructorParam2" });
instanceType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, null, instance, new object[] { "methodParam1", "methodParam2" });

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

...
<runtime>
    <assemblyBinding ...
        <probing privatePath="plugins" />
...

Вам нужно что-то сказать, какой тип реализовать (возможно, отображение конфигурации). Интерфейс, насколько я могу судить, просто предоставит контракт, который реализуют все плагины, чтобы обеспечить ожидаемый метод для вызова через отражение.

0 голосов
/ 06 ноября 2015

Я работаю над чем-то похожим, когда у клиента могут быть установлены разные версии сторонних DLL, хотя имя и местоположение совпадают.Если мы не ссылаемся на правильную версию, мы получаем ошибки.Я использую отражение для определения версии, но мне нужно либо изменить настройку для использования другого класса DAL в зависимости от версии, либо сделать версию DAL независимой через интерфейс.

Я склоняюсь ко второму.Если вы создадите в своем коде «фиктивную DLL», которая реализует интерфейс, который имеет все методы, которые вы хотите вызвать из целевой сборки, и передаете не фактический тип в качестве параметра, а интерфейс, то вы сможете использовать всеметоды в коде времени разработки и компиляции, основанные на ваших реализациях макета, и даже делают ваше тестирование, но затем, когда вы загружаете реальную сборку во время выполнения, получите результаты от реальной сборки. Дайте мне знать, если это работает для васи я дам вам знать.

Джои Морган

0 голосов
/ 30 апреля 2013
  string relative = "ClassLibrary1.dll";
            string absolute = Path.GetFullPath(relative);

            Assembly assembly = Assembly.LoadFile(absolute);
            System.Type assemblytype = assembly.GetType("ClassLibrary1.Class1");
             object []argtoppass={1,2};
          var a =Activator.CreateInstance(assemblytype, argtoppass);
          System.Type type = a.GetType();
          if (type != null)
          {
              string methodName = "add";
              MethodInfo methodInfo = type.GetMethod(methodName);
              object   result = methodInfo.Invoke(a, null);

              int a1 = (int )result;
          }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...