0

I'm using a method to have one VSIX extension for multiple versions of Visual Studio whereby I dynamically load the appropriate DLL based on the detected version. This works fine for most parts of my extension, but not my CodeLens extension.

The CodeLens part works fine when I target one version of visual studio and put it in the main project, but not when I put it as part of the dynamically included DLL. I believe this is because whatever Visual Studio runs to detect CodeLens classes (DataPoints etc.) is running before my extension loads the DLL, or it's using reflection on initially loaded DLLs, not MEF.

So, has anyone successfully managed to get this working? The only extension that includes CodeLens I'm aware of is Code Health and that has different installs for different versions of Visual Studio.

George Duckett
  • 31,770
  • 9
  • 95
  • 162

1 Answers1

0

There are a couple of things that need to be in place for this to work.

Create 2 class library projects named including the version of visual studio they should support (e.g. MyExtension.v14, MyExtension.v15 and put version specific code in there, including code that references specific versions of the assemblies but is otherwise identical.

Move your CodeLens classes there, but name the classes differently (otherwise one version will hide the other and MEF will only work for one version of Visual Studio). In my project I added text templates to one of the project that read the cs files from the other and replaced the class names.

In your vsix manifest file add 2 MefComponent asset entries, pointing to each of your library projects.

Reference your library projects from the main project, but under the reference entry set Reference Output Assembly to False and set Output Groups Included in VSIX to BuiltProjectOutputGroup;BuiltProjectOutputGroupDependencies;GetCopyToOutputDirectoryItems;SatelliteDllsProjectOutputGroup and Output Groups Included in VSIX (Local Only) to DebugSymbolsProjectOutputGroup;

In your Package's start up code somewhere detect the VS version running and load the appropriate assembly:

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"));
}

This last step may not be needed for MEF to work, however I needed it as the version specific DLLs also included types I needed for other functionality in my package.

In order for CI etc. to work, and probably specific to code-lens extensions, add the version specific DLLs as solution items, and reference those, rather than referencing a folder on your computer.

For reference see the changeset 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.

George Duckett
  • 31,770
  • 9
  • 95
  • 162