我正在开发一个嵌入Mono的应用程序,我想将一个事件从C ++层引发到C#层。这就是我所拥有的:
void* itr(NULL);
MonoEvent* monoEvent;
while(monoEvent= mono_class_get_events(klass, &itr))
{
if(0 == strcmp(eventName, mono_event_get_name(monoEvent)))
raiseMethod = mono_event_get_raise_method(monoEvent);
}
但是,raiseMethod总是以NULL形式返回。看一下MonoEvent的结构,看起来像是添加和删除方法,但不是加注?为了让它发挥作用,我有什么特别的事情要做吗?
编辑:如果重要,这里是我在C#层使用的委托,类和事件的(基本)形式。
public delegate void MyHandler(uint id);
public class SimpleComponent : NativeComponent
{
public event MyHandler OnEnter;
public event MyHandler OnExit;
}
答案 0 :(得分:5)
可以在父类中定义事件吗?如果是这样,您需要使用以下内容遍历类层次结构:
MonoEvent* monoEvent;
while (klass)
{
void* itr = NULL;
while(monoEvent= mono_class_get_events(klass, &itr))
{
if(0 == strcmp(eventName, mono_event_get_name(monoEvent)))
raiseMethod = mono_event_get_raise_method(monoEvent);
}
klass = mono_class_get_parent(klass);
}
在评论和重新阅读问题后编辑:
事件的raise方法为NULL是正常的。
对于使用C#事件关键字或Visual Basic Event关键字声明的事件,此方法通常返回null。这是因为C#和Visual Basic编译器默认情况下不会生成这样的方法。
(source)
恐怕发起课堂活动可能很难。因为它实际上打破了.NET中事件的概念 - 它说类本身只能触发自己的事件。实际上,即使是C#也很难引起其他类的事件。
从概念上讲,事件是add_handler和remove_handler方法的对,您可以在其中指定在事件发生时要调用的委托。它是如何实现事件的。从技术上讲,它只是一个私人代表领域,AFAIK。 您可以尝试找到它。
我不确定这是否是一种正确的方法,但How do I raise an event via reflection in .NET/C#?中的一个答案描述了如何使用反射引发事件。您可能会尝试将其转换为mono_class / mono_field调用等。
答案 1 :(得分:3)
Krizz的答案是最完整的。这就是我修改代码的方式,以便我按照“期望”的方式工作。
我将C#更改为:
public delegate void MyHandler(uint aEntityId);
public class SimpleComponent: NativeComponent
{
public event MyHandler OnEnter;
public event MyHandler OnExit;
protected void CallOnEnter(uint aEntityId)
{
if (OnEnter != null)
OnEnter(aEntityId);
}
protected void CallOnExit(uint aEntityId)
{
if (OnExit!= null)
OnExit(aEntityId);
}
}
然后用
抓住单声道方法raiseMethod = mono_class_get_method_from_name(klass, "CallOnEnter", 1);