为什么不是所有的 EnvDTE 程序集都是主互操作的...我是 COMfused?

Why aren't all EnvDTE assemblies Primary Interop...I'm COMfused?

我正在尝试了解 Visual Studio EnvDTE 互操作程序集的工作原理,以及它们为何以这种方式设计。新程序集包含updated/new个接口,微软推荐使用VS2017最新的接口。看起来像这样:

EnvDTE.DTE dte = (EnvDTE.DTE)((IServiceProvider)Host).GetCOMService(typeof(DTE));
EnvDTE80.DTE2 dte2 = (EnvDTE80)dte;
EnvDTE.Solution solution = dte2.Solution; // Returns a Solution type, not Solution2
EnvDTE80.Solution2 solution2 = (EnvDTE80.Solution2)dte2.Solution; 

在该片段中,DTE2.Solution 属性 returns 类型 Solution and not Solution2 如我所料...您必须显式强制转换才能访问较新的接口,这似乎很奇怪。

我在注册表中搜索了 EnvDTExxx 程序集的每个 GUID,但我找到的唯一引用其中任何一个的 CLSID 是 Microsoft Visual Studio DTE 对象Microsoft Visual Studio 解决方案对象。 link 到 EnvDTE 作为它们的类型库...而且我找不到任何使用更新的 EnvDTExxx 版本的 COM 对象。然而我在 OleView 中看到了最新的界面!!! :

这是否意味着较新的 ​​EvDTExxx 程序集依赖于原始的 EnvDTE 来访问实际的 COM 组件?我相信 OleView 中的接口代表 COM 组件上的实际接口......但是为什么 EnvDTE 类型库不使用更新的 DTE2 接口?

更让我困惑的是,我发现只有 EnvDTE 和 EnvDTE80 装饰有 PrimaryInteropAssemblyAttribute... 而 EnvDTE90-100 则没有!我假设因为较新的互操作程序集仅公开 EnvDTE(PIA)的类型,所以不会有类型冲突?但这并不能解释为什么 EnvDTE80 也被标记为 PIA……我认为只能有一个 PIA!

请把我从 COMfusion 中解救出来!

Com 类型实际上只是接口,它遵循与 .NET 接口相同的规则。

在接口中,您无法在不破坏二进制兼容性的情况下更改派生方法中已定义方法的 return 类型。

所以因为接口本质上是

public interface EnvDTE 
{
    Solution Solution {get;}
    //other stuff
}

public EnvDTE80 : EnvDTE
{
    //more other stuff
}

return 必须相同才能保持二进制兼容性。