C ++ / CLI为任何事件

时间:2017-11-22 13:39:44

标签: c++-cli

我试图将.NET库公开给我公司的产品 将它们包装在我们的自定义JavaScript引擎中。到目前为止,它已经到了 一直很顺利,但我在包装时遇到了一些问题 .NET事件。

似乎C#中的事件可能有非常不同的代理,例如

public class Box
{
    public event EventHandler changeSize;
    public delegate void NameDelegate(string name);
    public event NameDelegate changeName;
}

如果可能的话,我想支持将它们暴露给所有人 JavaScript引擎。我设法支持特定事件 使用助手类:

ref class DotNetEventHandler
{
public:
    DotNetEventHandler(DotNetObject *dotNetObj,
                       EcmaScript::GlobalObject *globalObj,
                       System::String^ eventType);

    ~DotNetEventHandler();

    // This method can handle events with the same signature, 
    // e.g. the Box::changeSize event in the prev. code sample
    void eventHandler(System::Object ^object, System::EventArgs^ args);

    void setDelegate(System::Delegate ^del) { m_delegate = del; }
    System::Delegate^ getDelegate() { return m_delegate; }

    EcmaScript::UString eventType();

private:
    DotNetObject *m_dotNetObj;
    EcmaScript::GlobalObject *m_globalObj;
    System::String^ m_eventType;
    System::Delegate^ m_delegate;
};

然后使用事件处理程序:

void DotNetObject::AddEventListener(EcmaScript::Context& ctxt, const EcmaScript::UString& type, const EcmaScript::ValueRef& orListener, bool useCapture)
{
    try
    {
        System::Type^ objType = m_object->GetType();

        System::String^ eventType = gcnew System::String(type.c_str());
        auto eventInfo = objType->GetEvent(eventType);

        if(eventInfo != nullptr)
        {
            EcmaScript::GlobalObject *globalObj = dynamic_cast<EcmaScript::GlobalObject*>(ctxt.GlobalObject().SafeGlobalObjectPtr());
            auto eventHandler = gcnew DotNetEventHandler(this,globalObj, eventType);
            auto callback = eventHandler->GetType()->GetMethod("eventHandler");
            System::Delegate^ mdelegate = System::Delegate::CreateDelegate(eventInfo->EventHandlerType, eventHandler, callback);
            eventHandler->setDelegate(mdelegate);

            eventInfo->AddEventHandler(m_object, mdelegate);

            m_eventHandlers.push_back(eventHandler); 

        }
        else
            throw gcnew System::Exception(gcnew System::String("DotNetObject::AddEventListener() - could not find event: ") + eventType);
    }
    catch(System::Exception ^ex)
    {
        throw EcmaScript::ErrorCompletion(UStringFromString(ex->ToString()), ctxt.GetLineNo());
    }

    EcmaScript::Events::EventTargetObject::AddEventListener(ctxt, type, orListener, useCapture);
}

我想要的JavaScript API是这样的:

    sharpBoxDll = DotNetPlugin.load("SharpBox.dll");

    myBox = sharpBoxDll.create("Box");

    myBox.onchangeName = function(ev){
        alert("Box changed name to:" + ev.name);
    }

    ev = new Event();
    ev.initEvent("changeName",true,true);
    ev.args = "newBoxName";

    myBox.dispatchEvent(ev); 

有没有人知道是否可以按照我想要的方式创建任意数量的参数/类型的代理人?

编辑1:添加了关于如何使用DotNetEventHandler的示例代码。

编辑2:澄清:变量ev.args旨在将所有必需的参数提供为单个值或数组([])。

0 个答案:

没有答案