Как в 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
228 +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 Апр в 13:09
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Название заказа не должно быть пустым
Введите email
Бесплатные доработки
Гарантированные бесплатные доработки
Быстрое выполнение
Быстрое выполнение от 2 часов
Проверка работы
Проверка работы на плагиат
Интересные статьи из справочника
Поможем написать учебную работу
Название заказа не должно быть пустым
Введите email
Доверьте свою работу экспертам
Разместите заказ
Наша система отправит ваш заказ на оценку 92 648 авторам
Первые отклики появятся уже в течение 10 минут
Прямой эфир