我试图将.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旨在将所有必需的参数提供为单个值或数组([])。