Помогите, пожалуйста, разобраться с событиями и делегатами.
С одной стороны, у меня есть dll, написанная на C++/CLI. DLL должна инициировать события.
С другой стороны — C#-приложение, которое должно обрабатывать события от dll.
Привожу часть кода DLL:
public delegate void MyEventHandler(); // делегатpublic ref class clDriverMgr: System::Object
{
public:
event MyEventHandler^ MyEvent; // событие
...
Теперь привожу код из C#-приложения:
public delegate void MyEventHandler(); // всё тот же делегатpublic event MyEventHandler MyEvent; // событиеprivate void MyHandlerThrower() // обработчик события
{
...
}
// далее в коде есть строка, которая ищет событие в классе source (clDriverMgr) и добавляет к нему обработчик
source.GetEvent("MyEvent")
.AddEventHandler(instance,
new MyEventHandler(MyHandlerThrower));
Так вот на последней строке появляется Exception:
Невозможно преобразовать объект типа "VideoLink.Links.MyEventHandler" к типу "nsDriverMgr.MyEventHandler"
Поясню, что "VideoLink.Links.MyEventHandler" — это в C#, а "nsDriverMgr.MyEventHandler" — это для dll.
В принципе, понимаю, что что-то не так с делегатами, но что именно? Заранее благодарю за помощь.
Здравствуйте, chaika_sv, Вы писали:
_>Так вот на последней строке появляется Exception:
_>
_>Невозможно преобразовать объект типа "VideoLink.Links.MyEventHandler" к типу "nsDriverMgr.MyEventHandler"
_>Поясню, что "VideoLink.Links.MyEventHandler" — это в C#, а "nsDriverMgr.MyEventHandler" — это для dll. _>В принципе, понимаю, что что-то не так с делегатами, но что именно? Заранее благодарю за помощь.
Вы пытаетесь создать неправильный тип делегата.
Не нужно объявлять новый делегат в C# сборке, это будет другой тип, даже если имя совпадает.
Используйте MyEventHandler, объявленный с C++ (nsDriverMgr.MyEventHandler)
public event MyEventHandler MyEvent; // событиеprivate void MyHandlerThrower() // обработчик события
{
...
}
// далее в коде есть строка, которая ищет событие в классе source (clDriverMgr) и добавляет к нему обработчик
source.GetEvent("MyEvent")
.AddEventHandler(instance,
new nsDriverMgr.MyEventHandler(MyHandlerThrower));
V>Вы пытаетесь создать неправильный тип делегата. V>Не нужно объявлять новый делегат в C# сборке, это будет другой тип, даже если имя совпадает. V>Используйте MyEventHandler, объявленный с C++ (nsDriverMgr.MyEventHandler)
Да, спасибо. Теперь понимаю.
Но возникает ещё вопрос. Как "вытащить" этот делегат из сборки C++?
Я делаю так:
var asm = Assembly.LoadFile(assembly); // Сборкаvar del = asm.GetType("nsDriverMgr.MyEventHandler"); // Делегат
Тут всё проходит нормально. Делегат обнаруживается как класс, т.е. всё как и должно быть.
Дальше пытаюсь выполнить:
source.GetEvent("MyEvent") // имя события
.AddEventHandler(instance, // объект в C# (с ним всё в порядке)new del(MyHandlerThrower)); // создаю экземпляр только что полученного делегата del и добавляю в него обработчик события MyHandlerThrower
На это компилятор почему-то ругается (почему?):
error CS0246: The type or namespace name 'del' could not be found (are you missing a using directive or an assembly reference?)
Тогда пробую создать экземпляр делегата вручную с помощью, как я понимаю, "скрытого" конструктора:
Конструктор действительно такой существует и constructorInfoObj нормально инициализируется.
А вот дальше воспользоваться этим конструктором я не знаю как. Точнее знаю, что надо писать что-то вроде:
Здравствуйте, chaika_sv, Вы писали:
_>Тут всё проходит нормально. Делегат обнаруживается как класс, т.е. всё как и должно быть. _>Дальше пытаюсь выполнить: _>На это компилятор почему-то ругается (почему?):
Здравствуйте, chaika_sv, Вы писали:
_>Помогите, пожалуйста, разобраться с событиями и делегатами. _>С одной стороны, у меня есть dll, написанная на C++/CLI. DLL должна инициировать события. _>С другой стороны — C#-приложение, которое должно обрабатывать события от dll.
Зачем вам для этого события, не проще использовать для этого шаблон Observer? Если уж dll и приложение находится под вашим контролем...
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.