Ответ 1
tlbimp - это только начало проблемы.
Каждый COM-видимый объект .NET реализует IManagedObject. Каждый раз, когда вы пытаетесь вызвать объект через COM-интерфейс,.NET выполняет QueryInterface для IManagedObject, и если ему удастся, объект будет развернут и доступен напрямую. Устранение вызова interop таким образом считается оптимизацией производительности.
Это серьезная проблема в сценариях взаимодействия на основе COM, где на .NET-языках могут быть реализованы несколько компонентов. Если каждый компонент .NET реализует собственную версию COM-интерфейса, генерируемую tlbimp, они не смогут связываться друг с другом с помощью этого интерфейса. Несмотря на то, что каждая копия интерфейса Tlbimp'а имеет один и тот же COM-GUID,.NET рассматривает их отдельные интерфейсы. "Правильным" решением этой проблемы является определение COM-интерфейса в первичной сборке interop, и каждый компонент, внедренный .NET, использует эту же копию интерфейса, но если нет никакой координации между разработчиками компонентов, которые вряд ли произойдут.
Эта проблема была однажды подчеркнута разработчиком Microsoft в http://blogs.msdn.com/b/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspx вместе с решением для .NET 4, но она была основана на предварительная версия и не работает в финале. Я не знаю нигде, что он был признан Microsoft.
Одно из решений - отказаться от интерфейса в сценарии .NET-.NET и вместо этого использовать отражение. Это может работать во многих случаях, но, конечно, не очень впечатляет. Возможно, лучшим решением является использование неуправляемого кода для агрегирования каждого из ваших управляемых компонентов и отклонения попыток QueryInterface для IManagedObject. Это похоже на то, что описано в приведенной выше записи в блоге, но не полагается на функции .NET, которые больше не работают, как описано в этом блоге.
Взаимодействие .NET, IMO, довольно ужасное и явно нарушает правила COM (тот же интерфейс IID == тот же интерфейс и не должен заботиться о том, на каком языке реализуется объект). Но .NET вел себя так с самого начала, и никакая обратная связь от разработчиков, укушенных этим поведением, не изменила умов никого в команде .NET.