Я называю объект.NET или COM-объект?

Сегодня интересный вопрос возник. Скажем, у меня есть объект.NET, который реализует определенный интерфейс IMyInterface и является также Видимым COM.

Теперь, я загружаю тип из его ProgID и бросаю к интерфейсу со строгим контролем типов, как так:

IMyInterface objEarlyBound = null;
Type t = Type.GetTypeFromProgID("My.ProgId");
objLateBound = Activator.CreateInstance(t);

objEarlyBound= (IMyInterface)objLateBound;

objEarlyBound.Method();

Если я выполняю вышеупомянутый код, когда objEarlyBound. Метод () выполняется, я звоню в COM-объект или непосредственно в объект.NET? Как я могу доказать этот путь или другого?

7
задан Tim Long 4 March 2010 в 23:00
поделиться

2 ответа

Вы ничего не можете доказать в любом случае - это внутренняя реализация, которая намеренно скрыта от вас.

objEarlyBound и objLateBound должны иметь одинаковую идентификацию, то есть == для них вернет true.Таким образом, от каждого из них вы всегда можете получить другой и то же самое для любых других интерфейсов, которые они поддерживают, а также если вы назначите любой из них объекту . Но это мало что доказывает.

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

IMyInterface objEarlyBound = new MyClassExposedThroughCOM();

На этом этапе поддержка COM в CLR вообще не требуется. Но затем вы можете передать этот объект какой-нибудь внешней библиотеке COM, и в этот момент CLR создаст CCW для связи с объектом. И сделав это один раз, он всегда может вернуться к той же CCW для любого заданного объекта CLR.

Чтобы связать это с вашим примером, вы начинаете с RCW вокруг COM-объекта, вы приводите его к интерфейсу, и в этот момент CLR может (насколько нам известно) запросить специальный внутренний COM-интерфейс, который, в случае обнаружения позволяет ему получить доступ к внутреннему объекту CLR и, таким образом, полностью обойти COM с этого момента. Если в какой-то момент ему потребуется вернуться в CCW, он может это сделать, поскольку он должен иметь возможность сделать это в любое время при работе в другом направлении.

Я попытался установить точку останова в реализованной вручную функции QueryInterface COM-объекта C ++, чтобы узнать, что запрашивает среда CLR. По сути, он пробует много вещей, некоторые из которых я не мог сразу идентифицировать, так что он вполне может быть «обнюхиванием» другого объекта CLR. Это имеет смысл сделать это, чтобы избежать сумасшедшей ситуации сэндвича COM, в которой ссылка CLR указывает на RCW, которая указывает на CCW, которая указывает на объект CLR.Очевидно, это можно упростить, если ссылка CLR будет указывать непосредственно на объект CLR.

На самом деле теперь я думаю об этом, ему не нужно запрашивать, чтобы узнать это: у него есть глобальная таблица CCW, которую он сгенерировал ранее, поэтому он может просто искать любые новые IUnknown там. COM-объекты должны всегда возвращать один и тот же адрес для IUnknown , чтобы его можно было использовать для сравнения идентичности объектов. Следовательно, среда CLR всегда может распознать реализуемый ею COM-объект и получить соответствующий объект CLR.

Между прочим, все это обсуждение предполагает, что COM-объект находится в процессе. Если это вне процесса, тогда ситуация совершенно иная; у каждого процесса есть свой собственный экземпляр CLR, и поэтому он может также использовать COM-реализацию межпроцессного маршалинга.

2
ответ дан 7 December 2019 в 12:19
поделиться

RCW должны быть (насколько я знаю) специального типа System.__ComObject, однако, вероятно, вы хотите вызвать Marshal.IsComObject, который скажет вам, является ли объект оберткой во время выполнения или нет. В быстрой проверке COM-объект, созданный по этому маршруту, оказывается прямым управляемым объектом и теряет COM-обертку.

3
ответ дан 7 December 2019 в 12:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: