Я разрабатываю программу, которая использует плагины. Все плагины - это классы, которые наследуются от интерфейса KrotAPI.IKrotAPI. Интерфейс хранится в файле krotapi.cs, который распространен как для csproj хоста, так и для каждого плагина * .csproj.Как получить доступ к классу с интерфейсом из DLL?
Принимающие загружает плагины, используя этот код
dynamic LoadPlugin(Assembly asm)
{
foreach (Type type in asm.GetTypes())
{
if (type.GetInterface("KrotAPI.IKrotPlugin") != null)
{
PluginType = type;
dynamic inst = Activator.CreateInstance(type);
KrotAPI.IKrotPlugin inst2 = inst as KrotAPI.IKrotPlugin;
if (inst2 == null) return inst;
Console.WriteLine("Link to API is set up.");
return inst2;
}
}
throw new Exception("There are no valid plugin(s) in the DLL.");
}
В inst2
всегда пустой, и я вынужден использовать медленные и багги динамические вызовы. Как сделать это как inst
, но с KrotAPI.IKrotPlugin
типа?
Второй вопрос по почти той же теме. Некоторые функции плагинов возвращают результат типа KrotAPI.FindData (это структура, которая хранится в файле krotapi.cs). Но я не могу получить доступ к нему:
dynamic fd = new KrotAPI.FindData();
if (NextItemInfo != null) //NextItemInfo is an instance of that struct
fd = NextItemInfo;
listBox1.Items.Add(fd.FileName);
На последней строке NET Framework выдает это исключение:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException 'System.ValueType' не содержит определения для 'FileName'
однако поле FileName жестко закодировано в структуры и, конечно, не пустой, или
Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException Неожиданное исключение при связывании динамическую операцию
если заменить последнюю строку с KrotAPI.FindData fd2 = (KrotAPI.FindData) fd; listBox1.Items.Add(fd2.FileName);
.
WTF?
Спасибо! Какие проблемы могут возникнуть, когда я выбираю первый путь, а некоторые плагины будут старше или новее, чем хост exe?В настоящее время я вижу это лучше, потому что нет необходимости размещать в каталоге каждого плагина файл KrotAPI.dll, и когда в каталоге плагина нет файла Krot.exe, все все еще работает (как я полагаю, плагины используют сборка, которая уже загружена в память). –
Номер версии сборки является частью идентификатора сборки, который затем является частью идентификатора интерфейса. Это означает, что если вы обновите номер версии сборки узла, интерфейс, определенный этой сборкой, больше не является интерфейсом, который использовался сборками плагинов. Это можно немного смягчить путем связывания переадресаций. –
Вам не потребуется сборка API в каждом каталоге плагина. Если вы используете стандартную AppDomain, вы можете просто заставить приложение-хозяин загружать сборку API перед загрузкой любого из плагинов, а затем каждый плагин будет использовать уже загруженную сборку API. Вы можете принудительно загрузить сборку несколькими способами (обычно я использую пустой статический метод). Если вы изолируете каждый из своих плагинов в отдельном приложении AppDomain, это немного больше, но вы все равно можете использовать все плагины для использования центральной сборки API. –