Как правильно называть COM перечислители в .NET?

Я вызываю предоставляемую извне COM DLL, для которой сгенерировал оболочку взаимодействия COM. Ради аргумента, давайте назовем интерфейс, который я хочу вызвать IEnumFoo,

IEnumFoo имеет типичный шаблон перечислителя COM:

HRESULT Next (
ULONG        celt,
IFoo**       rgelt,
ULONG*       pceltFetched
);

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

Когда я выбираю «Добавить ссылку» и указываю Visual Studio на эту DLL, она создает сборку взаимодействия COM со следующей подписью:

void Next(uint, out IFoo, out uint)

Это позволяет только .NET-коду запрашивать один объект за один раз, что может значительно увеличить накладные расходы при использовании этих API.

Есть ли какой-то механизм, который я могу использовать для создания версии Next что позволило бы мне предоставить больше IFoo «слоты» над которыми бы маршалер был счастлив? (Я не против редактирования IL в сборке взаимодействия вручную :))

5

Решение

Подходящая подпись для этого будет выглядеть так:

void Next(
uint celt,
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] IFoo[] rgelt,
out uint pceltFetched);

Согласно MSDN, по крайней мере, нет механизма, чтобы генерировать это автоматически. Даже если оригинальный IDL для интерфейса имел length_is применительно к rgelt, эта информация теряется в библиотеке типов. Поэтому вам нужно отредактировать сборку взаимодействия вручную.

Еще один вариант — полностью определить этот конкретный интерфейс вручную в основной сборке и просто игнорировать созданную версию взаимодействия. Помните, что при приведении типов к RCW будет работать любой интерфейс с совпадающим GUID (т. Е. Тот, для которого QueryInterface успешен), поэтому вы можете иметь несколько разных управляемых интерфейсов, которые представляют разные представления одного и того же COM-интерфейса.

3

Другие решения

Не ответ на ваш вопрос, а предложение попробовать другой подход. Я бы создал оболочку C ++ / CLI для перечисления через интерфейс COM в неуправляемом коде (таким образом, избегая маршалинга), а затем создавал управляемый List или другой контейнер, в котором вы возвращаете свои объекты.

Это почти наверняка будет проще, чем ручная настройка IL сборки взаимодействия, и вы также можете легко отладить его. Неуправляемый код C ++ будет довольно простым, как и управляемая оболочка.

2

Если объект, реализующий этот интерфейс, является нативным, просто переопределите интерфейс в своем коде, как и должно быть, убедившись, что в интерфейсе используются те же атрибуты ComImport и Guid. Затем возьмите объект и приведите к своему интерфейсу. Вы можете звонить через этот интерфейс просто отлично.

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

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector