4

I'm authoring a Visual Studio extension and I want to [Export] a different implementation of a given interface based on which Visual Studio version is running - for instance, one implementation for Visual Studio 2010 and 2012 and a different one for Visual Studio 2013 and Visual Studio "14".

I realize I could simply deploy a different DLL for each Visual Studio version, but I'm wondering if there's a way to avoid that - shipping the same DLL and the same vsixmanifest, but having my extension dynamically [Export] the correct version of the interface.

What is the most eloquent way to do this?

Omer Raviv
  • 11,409
  • 5
  • 43
  • 82

3 Answers3

2

You could export a single class which implements the interface and have that class function as a proxy to the actual implementation according to the visual studio version. For example:

[Export(typeof(IMyInterface))]
public class ProxyClass : IMyInterface
{
    private IMyInterface impl;
    public ProxyClass()
    {
        if (IsVs2014())
        {
            impl = new Vs2014Impl();
        }
        else
        {
            impl = new Vs2013Impl();
        }
    }

    public void DoSomething()
    {
        impl.DoSomething();
    }
}
Adi Lester
  • 24,731
  • 12
  • 95
  • 110
  • For reference, this is similar to what @JaredPar does in VsVim, using a Factory instead of a Proxy - There's an ISharedService interface and an [SharedServiceFactory.cs](https://github.com/jaredpar/VsVim/blob/848f333b942eaa2ddde2cbfb08362d03d0491f7a/Src/VsVimShared/Implementation/SharedService/SharedServiceFactory.cs) which `Imports` all the different implementations and selects the correct one per VS Version. – Omer Raviv Sep 21 '14 at 13:55
2

It's not clear from your question that you actually need to have separate exports. Several options for supporting multiple versions of Visual Studio are available:

  1. Identify the minimum version of Visual Studio you wish to support, and only reference immutable and/or versioned assemblies from that version of Visual Studio and earlier. Your extension will likely work across multiple versions without changes or special considerations. This is the best option whenever "reasonably" possible.

  2. Export a single item, but implement it using assemblies that target specific versions of Visual Studio. For example, my Inheritance Margin extension requires a reference to an unversioned assembly, so I need to include separate implementations for each supported version of Visual Studio. It is implemented by providing a single common exported object CSharpInheritanceTaggerProvider, but the implementation of the tagger itself is delegated to a dynamically selected assembly.

  3. Export multiple items, but only perform operations within the one relevant to the current version of Visual Studio. The GitDiffMargin extension uses this feature to place the scroll margin control in the most appropriate location. While the assembly doesn't require any reference to unversioned assemblies, starting in Visual Studio 2013, the optimum location for this margin in the UI changed, and MEF metadata attributes statically determine the placement.

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
0

I haven't tried this, just thought this in few minutes, perhaps it can work:

public enum VisualStudioVersion
{
    Unknown,

    VS2010,
    VS2012,
    VS2013,

    VS14
}

public class VsSpecificExportAttribute : ExportAttribute
{
    // the place for this is not right,
    // but you can figure this out on your own.
    private static VisualStudioVersion _currentVisualStudioVersion =
        VisualStudioVersion.VS2013;

    class DummySentil{}

    public VsSpecificExportAttribute(Type typeToExport, 
        VisualStudioVersion visualStudioVersion)
        : base(visualStudioVersion == _currentVisualStudioVersion ?
                typeToExport : typeof(DummySentil))
    {
    }
}

then you could use it as;

[VsSpecificExport(typeof(IWpfTextViewCreationListener), VisualStudioVersion.VS14)]
public class MyTextViewCreationListener: IWpfTextViewCreationListener
{

}

The underlying idea is that the "VsSpecificExport" attribute decides wheenever we are on correct "visual studio version", and if we are not, we are going to export "DummySentil" class that does absolutely nothing and is used by noone.

Erti-Chris Eelmaa
  • 25,338
  • 6
  • 61
  • 78