Как в C# пробросить интерфейс через dynamic? Доброго времени суток! Пишу программу с плагинами. Все плагины это классы, реализующие интерфейс KrotAPI.IKrotPlugin. Пространство имён KrotAPI берётся из общего для всех проектов плагинов файла krotapi.cs. Этот же файл прикреплён к проекту хоста. Процедура загрузки плагина хостом такова: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("Есть привязка к стандартному API.");
return inst2;
}
}
throw new Exception("Нет плагинов Крота в сборке.");
}
Проблема в чём. Загрузить плагин удаётся только в переменную inst, в inst2 возвращается null несмотря на то, что Activator.CreateInstance(type) возвращает класс, наследующийся от KrotAPI.IKrotPlugin. Видимо CLR не нравится, что интерфейс класса находится в другой сборке, хоть и по исходникам он идентичен одноимённому интерфейсу из сборки хоста. Можно ли как-то переубедить CLR, что inst это KrotAPI.IKrotPlugin? Т.е. сделать утиную типизацию.
И второй вопрос, сразу. Если сие не по силам .NET Framework (4.0), то как сделать возможность обращения плагина к такой функции в хосте:int HostEar(string Command, Dictionary Arguments, out object Result)
? Если гнать через Delegate, то затыка идёт в передаче out, компилятор слово out не принимает, а без него возникает ошибка рантайма, мол, не найдена функция с таким количеством аргументов.
Делегат "статический" (delegate с маленькой буквы), отлично проходящий между классами внутри хоста, при передаче в плагин через метод либо свойство рушит хост с такими матюками:Microsoft.CSharp.RuntimeBinder.RuntimeBinder
Internal Compiler Exception
An unexpected exception occurred while binding a dynamic operation
. То есть тоже утиная типизация не срабатывает, даже когда этот делегат я размещаю в krotapi.cs.

21 Авг 2019 в 07:02
246 +1
0
Ответы
1

Для того чтобы привести dynamic объект к интерфейсному типу, можно воспользоваться ключевым словом as, как вы уже сделали в вашем коде. Однако, если результат приведения as равен null, то значит, что объект не является экземпляром данного интерфейса.

Чтобы работать с методом HostEar в плагине, можно воспользоваться делегатами. Однако, в вашем случае возникает ошибка RuntimeBinder, скорее всего из-за того, что делегат передается через dynamic. Попробуйте создать делегат с явным типом и пробросить его через dynamic. Например:

public delegate int HostEarDelegate(string Command, Dictionary<string, object> Arguments, out object Result);
dynamic plugin = LoadPlugin(assembly);
if (plugin is IKrotPlugin)
{
HostEarDelegate hostEar = new HostEarDelegate(plugin.HostEar);
object result;
int returnValue = hostEar("Command", new Dictionary<string, object>(), out result);
}

Если проблема с RuntimeBinder останется, то возможно вам стоит попробовать использовать явные типы вместо dynamic там, где это возможно, чтобы избежать ошибок времени выполнения.

20 Апр 2024 в 13:09
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир