C# динамически использует функции DLL

У меня есть две папки, одна папка с файлами, а другая с файлами DLL, я не могу знать, какие или сколько библиотек DLL находится в каталоге файлов DLL (модульное использование). Внутри каждого DLL-файла есть функция, которая получает FileInfo в качестве параметра. Как я могу запустить все функции в DLL-файлах для каждого файла из каталога файлов?

например, один из файлов DLL:

using System;
using System.IO;
namespace DLLTest
{
    public class DLLTestClass
    {
        public bool DLLTestFunction(FileInfo file)
        {
            return file.Exists;
        }
    }
}

Главный:

DirectoryInfo filesDir = new DirectoryInfo(path_to_files_Directory);
DirectoryInfo dllsDir = new DirectoryInfo(path_to_dlls_Directory);

foreach(FileInfo file in filesDir.getFiles())
{
    //How do I run each one of the dll funtions on each one of the files?
}

Большое спасибо.

3 ответа

Решение

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

Вы должны создать один проект (называемый ModuleInterface или что-то еще) с одним интерфейсом:

public interface IDllTest
{
    bool DLLTestFunction(FileInfo file);
}

Тогда у всех ваших Dll-проектов должен быть хотя бы один класс, реализующий этот интерфейс:

public class DLLTestClass : IDllTest
{
    public bool DLLTestFunction(FileInfo file)
    {
        return file.Exists;
    }
}

Обратите внимание на реализацию IDllTest выше (вы должны добавить ссылку на проект ModuleInterface).

Наконец, в вашем основном проекте вы должны загрузить все свои сборки из каталога:

DirectoryInfo dllsDir = new DirectoryInfo(path_to_dlls_Directory);

foreach(FileInfo file in dllsDir.getFiles())
{
    //Load the assembly
    Assembly assembly = Assembly.LoadFile (file.FullName);

    //Get class which implements the interface IDllTest
    Type modules = assembly.GetTypes ().SingleOrDefault(x => x.GetInterfaces().Contains(typeof(IDllTest)));
    //Instanciate
    IDllTest module = (IDllTest)Activator.CreateInstance (modules);

    //Call DllTestFunction (you have to define anyFileInfo)
    module.DLLTestFunction(anyFileInfo);
}

Это, вероятно, нуждается в некоторых корректировках, потому что я не тестировал его! Однако я уверен, что это шаги, чтобы следовать.

Ссылка (на французском): http://www.lab.csblo.fr/implementer-un-systeme-de-plugin-framework-net-c/

Я надеюсь, что мой английский понятен, не стесняйтесь поправлять меня.

Нильс предложил очень хорошее решение с понятным интерфейсом. Если вы не хотите создавать интерфейс или не можете, вы можете использовать все типы и методы для поиска известной сигнатуры:

var definedTypes = Assembly.LoadFile("file").DefinedTypes;
foreach(var t in definedTypes)
{
    foreach(var m in t.GetMethods())
    {
        var parameters = m.GetParameters();
        if (parameters.Length ==1 && parameters[0].ParameterType == typeof(FileInfo))
        {
            var instanse = Activator.CreateInstance(t);
            m.Invoke(instanse, new[] { fileInfo });
         }
     }
}

для этого вам нужно, чтобы у всех классов был конструктор без параметров для его создания. В качестве параметра Invoke метод, который вы даете свой объект fileInfo.

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

Другие вопросы по тегам