Я вызываю объект .NET или COM-объект? - PullRequest
7 голосов
/ 05 марта 2010

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

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

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

objEarlyBound= (IMyInterface)objLateBound;

objEarlyBound.Method();

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

Ответы [ 2 ]

3 голосов
/ 05 марта 2010

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

2 голосов
/ 05 марта 2010

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

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

Если вы прямо ссылались на сборку, содержащую класс, предоставляемый через 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-реализацию межпроцессного маршалинга.

...