创建包含 CodeLens 的多目标 VS 版本扩展

Creating a multi-targeting VS-version extension that includes CodeLens

我正在使用一种方法为 Visual Studio 的多个版本提供一个 VSIX 扩展,从而根据检测到的版本动态加载适当的 DLL。这适用于我的扩展的大部分,但不适用于我的 CodeLens 扩展。

当我以 visual studio 的一个版本为目标并将其放在主项目中时,CodeLens 部分工作正常,但当我将其作为动态包含的 DLL 的一部分时,则无法正常工作。我相信这是因为在我的扩展加载 DLL 之前,无论 Visual Studio 运行以检测 CodeLens 类(DataPoints 等)是 运行,或者它在初始加载的 DLL 上使用反射,而不是 MEF。

那么,有没有人成功地让这个工作?我所知道的包含 CodeLens 的唯一扩展是 Code Health 并且对于 Visual Studio.

的不同版本具有不同的安装

要实现这一点,需要准备好几件事情。

创建 2 个 class 库项目,命名包括它们应该支持的 visual studio 版本(例如 MyExtension.v14MyExtension.v15 并将特定于版本的代码放在那里,包括代码引用特定版本的程序集,但在其他方面相同。

将您的 CodeLens classes 移到那里,但以不同的方式命名 classes(否则一个版本将隐藏另一个,MEF 将仅适用于 Visual Studio 的一个版本)。在我的项目中,我将文本模板添加到其中一个项目,该项目从另一个项目读取 cs 文件并替换了 class 名称。

在您的 vsix 清单文件中添加 2 个 MefComponent 资产条目,指向您的每个库项目。

从主项目引用您的库项目,但在引用条目下将 Reference Output Assembly 设置为 False 并将 Output Groups Included in VSIX 设置为 BuiltProjectOutputGroup;BuiltProjectOutputGroupDependencies;GetCopyToOutputDirectoryItems;SatelliteDllsProjectOutputGroupOutput Groups Included in VSIX (Local Only)DebugSymbolsProjectOutputGroup;

在你的包的启动代码中某处检测 VS 版本 运行 并加载适当的程序集:

private int GetMajorVsVersion()
{
    var dte = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE));
    Version version;
    if (Version.TryParse(dte.Version, out version))
    {
        return version.Major;
    }
    return 15;
}
private Assembly GetVersionedAssembly()
{
    return Assembly.LoadFrom(Path.Combine(Path.GetDirectoryName(typeof(MyExtensionPackage).Assembly.Location), $"MyExtension.v{GetMajorVsVersion()}.dll"));
}

MEF 工作可能不需要这最后一步,但我需要它,因为特定于版本的 DLL 还包括我包中其他功能所需的类型。

为了 CI 等工作,并且可能特定于代码镜头扩展,添加版本特定的 DLL 作为解决方案项目,并引用它们,而不是引用计算机上的文件夹。

参考变更集here where I did most of the work to make the extension support multiple versions. See subsequent changesets where I sorted out the referencing issue with a snapshot of it working having just made the changes here