Как в 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.
Для того чтобы привести 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 там, где это возможно, чтобы избежать ошибок времени выполнения.
Для того чтобы привести 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 там, где это возможно, чтобы избежать ошибок времени выполнения.