Search code examples
c#visual-studio-2010visual-studiovisual-studio-2012vsix

How to package a VSIX-based extension for multiple Visual Studio versions?


I am maintaining a company internal Visual Studio extension that is packaged and deployed as VSIX container. This extension currently targets VS 2010. It uses several VS API DLLs and references the VS 2010 versions of them.

I am currently migrating this extension to be compatible with VS 2012/2013. I already found out that the old VSIX manifest can be edited manually to allow the extension to additionally install to VS 2012/2013 - this works perfectly.

However some of the VS 2010 APIs I am currently using are not compatible with VS 2012++ and I need to update them - with the effect of giving up backward compatibility.

My question is: How should I structure my solution and VSIX so that It will be compatible with VS 2010, 2012 and 2013. Would it work to have one DLL targeting VS 2010 and one DLL targeting VS 2012/2013 and picking the one to use at extension load time?

Side note: I am using MEF to compose my internal functional units. Does that make it easier in any way?


Solution

  • You may:

    1. decouple the functionality exposed by the two version-specific assemblies into an ad-hoc interface (which you can put itself into the host assembly, if you wish), as you may do with every other MEF plugin; let's call it IDoWork;
    2. implement the aforementioned interface in two concrete types, exposed by two different assemblies, one for each VS version you are supporting, e.g. DoWorkVs2010 and DoWorkVs2012;

      • AssemblyForVS2010.dll -> DoWorkVs2010 : IDoWork
      • AssemblyForVS2012.dll -> DoWorkVs2012 : IDoWork

    . 3. (optional) [Export] the two types, to make them available through MEF; e.g.:

        [Export(typeof(IDoWork))]
        class DoWorkVs2010 : IDoWork
        {
            // ...
        }
    

    4. add a factory to your host assembly (the one loaded directly with your VSX) and, from there, build the concrete type you are looking for, based on the DTE version:

        static class DoWorkFactory
        {
            internal static IDoWork Build()
            {
                // Load the version-specific assembly
    
                // - Via reflection (see http://stackoverflow.com/a/465509/904178)
                // - Or via MEF
    
                return ...;
            }
        }