Перегрузки в COM-взаимодействии (CCW) — имена IDispatch включают суффикс (_2, _3 и т. д.)

У меня есть управляемая сборка, содержащая несколько классов, и эти классы имеют перегруженные методы. Я предоставляю сборку вызывающим COM/IDispatch через

[ComVisible(true)]

.. а также установить правильный Guid на самой сборке. Я не определяю явный интерфейс для COM-взаимодействия. Все делается динамически. Я запускаю regasm.exe /codebase в управляемой DLL, и она регистрирует ее для COM-взаимодействия.

Когда я запускаю OleView, я вижу ProgId различных классов в сборке. Но при просмотре этих ProgId и расширении узла IDispatch для этих классов нет информации TypeLib.

Тем не менее, из сценария я могу вызвать метод, который не принимает аргументов, или метод, который принимает один аргумент. Если также имеется перегрузка, которая принимает более одного аргумента, я не могу вызвать этот метод по имени. Ошибка, которую я постоянно получаю,

Microsoft VBScript runtime error: Wrong number of arguments or invalid property assignment:  <methodname>

Из этого я понял, что клиенты COM/IDispatch не могли правильно разрешать перегруженные методы для объекта, доступного через COM-взаимодействие.


Затем я добавил

[ClassInterface(ClassInterfaceType.AutoDual)]

... для каждого из рассматриваемых классов. После regasm.exe в DLL я могу видеть информацию о typelib для каждого метода в узле IDispatch.

Я обнаружил, что перегруженные методы автоматически получают имя, содержащее добавленный суффикс. MethodX будет предоставлять перегрузки в автоматически сгенерированной сборке библиотеки типов как MethodX, MethodX_2, MethodX_3 и т. д.

И я обнаружил, что, ссылаясь на имена методов с этими суффиксами, я могу вызывать перегруженные методы, хотя и не с обычным именем.

Что еще интереснее, если бы я затем удалил [ClassInterface(ClassInterfaceType.AutoDual)] из классов, я мог бы по-прежнему вызывать перегруженные методы таким образом, избегая, таким образом, ошибки Wrong number of arguments or invalid property assignment.

У меня вопрос: стабильно ли такое поведение — добавление числовых суффиксов к именам членов? задокументировано? надежный?


person Cheeso    schedule 14.08.2009    source источник


Ответы (3)


COM не поддерживает перегрузку методов, поэтому уровень .NET COM Interop приходится импровизировать. Я не уверен, что искажение имен, как вы описали, задокументировано где-либо, но даже если это так, я не думаю, что его использование - хорошая идея - это все еще довольно неудобный API для пользователей COM. Если вы хотите открыть свои классы для COM, лучший способ — написать отдельный интерфейс [ComVisible], удобный для COM, и скрыть сам класс. Правильный способ обработки перегрузок в COM-дружественном виде - иметь один метод с некоторыми [Optional] аргументами (и делегировать соответствующие перегрузки .NET).

person Pavel Minaev    schedule 15.08.2009

По моему опыту, взаимодействие с генерацией Method, Method_1, Method_2 и т. д. является нормальным и стабильным, но не очень желательным. Раздражает, что перегрузки не пересекают границу управляемого/неуправляемого. Вместо того, чтобы произвольно добавлять числовой суффикс к моим методам, я пытаюсь реорганизовать методы COM-Visible в отдельные методы с уникальными именами, чтобы потребителю COM было более очевидно, что вызывается.

person C-Pound Guru    schedule 15.08.2009

Да, это задокументировано в MSDN:

Поскольку его изменение будет «критическим изменением» задокументированной функции, я думаю, вы можете полагаться на его «стабильность». Большим недостатком является то, что имена ваших методов зависят от порядка, в котором они определены в исходном файле.

Обратите внимание, однако, что COM поддерживает необязательные аргументы, поэтому их использование может быть жизнеспособной альтернативой перегрузкам. Если вам нужно добавить перегрузки для бинарной совместимости со старыми клиентами .NET вашей библиотеки, я считаю полезным следующий шаблон:

// used for binary-compatibility with .NET clients who currently use 
// the old, one-parameter version
[ComVisible(false)]
void myMethod(String oneParameter) {   
    ... 
}   

// since this is the first COM-visible version, it is assigned the "correct" name.
void myMethod(String oneParameter, int newParameter = 0) {
    ...
}

Поскольку COM поддерживает необязательные параметры, будут работать как myMethod(string), так и myMethod(string, int).

person Heinzi    schedule 25.10.2012
comment
Примечание. При использовании VB.NET для этого метода (две перегрузки, отличающиеся только необязательными параметрами) требуется VS 2012. - person Heinzi; 21.11.2012