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