0

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

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

那么,有没有人成功地设法让这个工作?我知道的唯一包含 CodeLens 的扩展是Code Health,它对不同版本的 Visual Studio 有不同的安装。

4

1 回答 1

0

有几件事需要到位才能使其发挥作用。

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

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

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

从主项目引用您的库项目,但在设置Reference Output AssemblyFalse和设置Output Groups Included in VSIXBuiltProjectOutputGroup;BuiltProjectOutputGroupDependencies;GetCopyToOutputDirectoryItems;SatelliteDllsProjectOutputGroup和的参考条目Output 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 添加为解决方案项,并引用它们,而不是引用计算机上的文件夹。

作为参考,请参阅此处的变更集,我在其中完成了大部分工作以使扩展支持多个版本。请参阅随后的变更集,其中我整理了引用问题,并在此处进行了更改,并提供了它的工作快照。

于 2016-09-12T06:51:40.750 回答