Я создаю приложение для сценариев, используя собственный API-интерфейс Windows и движок JavaScript chakrart. В моем IDL есть интерфейсы, подобные следующим:
[oleautomation, dual, nonextensible,
uuid(...)]
interface IMyInterface : IDispatch
{
[id(MYDISPID_EVENT), propget] HRESULT Event(BSTR strEventName, [out, retval] IDispatch ** ppHandler);
[id(MYDISPID_EVENT), propput] HRESULT Event(BSTR strEventName, IDispatch * pHandler);
};
Я смог без особых проблем добавлять собственные объекты в движок chakrart (используя JsVariantToValue, а затем устанавливая свойство для глобального объекта текущего контекста). Однако, когда я пытаюсь установить обработчик событий, я получаю сообщение об исключении "Объект не поддерживает это свойство или метод".
Я пробовал следующие варианты синтаксиса:
object.Event["foo"] = handler;
object.Event("foo", handler);
object.put_Event("foo", handler);
object.Event("foo") = handler;
Последнее близко к тому, как это будет сделано с помощью vbscript:
object.Event("foo") = GetRef("handler)
Если я использую синтаксис метода в IDL, как показано ниже, я просто предпочел бы использовать присвоение свойств, если это возможно.
[id(MYDISPID_GETEVENT)] HRESULT GetEvent(BSTR strEventName, [out, retval] IDispatch ** ppHandler);
[id(MYDISPID_SETEVENT)] HRESULT SetEvent(BSTR strEventName, IDispatch * pHandler);
А также обратите внимание, что простые присваивания свойств работают, только когда я пытаюсь проиндексировать свойства, которые он ломает. Я понимаю, что JavaScript делает что-то очень отличное от синтаксиса object [prop], по крайней мере для родных объектов JavaScript. Возможно, это просто несовместимость в слое взаимодействия chakrart?
Я подтвердил способ выполнения этого с желаемым синтаксисом (App.Event ['foo'] = someHandler;). Как уже упоминалось, я уже знал, что JavaScript рассматривает имя ['foo'] как поиск члена по имени
Попросите объект App реализовать propget для события, которое возвращает объект с пользовательской (недвойственным интерфейсом) реализацией IDispatch. Этот объект хранит карту имен для DISPID и всякий раз, когда неизвестное имя запрашивается через GetIDsOfNames, возвращается ранее не назначенный DISPID.
Обратите внимание, что для соблюдения правил для IDispatch объект должен отслеживать имена, даже если нулевой обработчик впоследствии назначен для данного имени, так что тот же DISPID всегда будет возвращен для определенного имени.