【问题标题】:Embedded Mono: How do you raise an event in C++?Embedded Mono:如何在 C++ 中引发事件?
【发布时间】:2012-01-31 22:42:23
【问题描述】:

我正在开发一个嵌入 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 的结构,似乎填充了 add 和 remove 方法,但没有填充 raise?我需要做些什么特别的事情才能让它发挥作用吗?

编辑:如果重要的话,这里是我在 C# 层中使用的委托、类和事件的(基本)形式。

public delegate void MyHandler(uint id);
public class SimpleComponent : NativeComponent
{
    public event MyHandler OnEnter;
    public event MyHandler OnExit;
}

【问题讨论】:

    标签: c# c++ events mono


    【解决方案1】:

    可以在父类中定义事件吗?如果是这样,您需要使用以下内容遍历类层次结构:

    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);
    }
    

    在评论和重新阅读问题后编辑

    event的raise方法为NULL是正常的。

    对于使用 C# event 关键字或 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 调用等。

    【讨论】:

    • 不。通过调试,我已经验证我正确地恢复了事件。只是 mono_event_get_raise_method 返回 null。 get_add_method 和 get_remove_method 返回值。
    【解决方案2】:

    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);
        }
    }
    

    然后用

    抓取mono方法
    raiseMethod = mono_class_get_method_from_name(klass, "CallOnEnter", 1);
    

    【讨论】:

    • 呸,打败我。无论如何,这几乎是 .NET 中的约定。事件的文档使用它(Raising an Event 和相关的How To),它也在框架类的所有地方使用。次要问题:命名约定将使 EnteringExiting 成为事件字段的“正确”名称,OnEntering() / OnExiting 应该用于引发它们的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 2016-09-28
    相关资源
    最近更新 更多