This project is read-only.

MEF composition in DiagnosticAnalyzer


While trying to implement a larger system composed of several refactorings and analyzers, I wanted to provide an easy way of sharing settings between the classes. I started implementing this by using MEF-based DI in VS2013 - MEF 1.

After I switched to VS 2015 Preview, I had to upgrade most of the code, including a change in MEF version - portable libraries must use MEF 2. After the upgrade, the whole composition stopped working altogether. I spent the whole of today trying t figure out what went wrong.

I ended up with a test project that can reproduce the behavior (I can provide it if deemed necessary).

The core problem seems to be the fact that classes that inherit from DiagnosticAnalyzer never participate in MEF composition, even if explicitly decorated with [System.Composition.Export] and [DiagnosticAnalyzer] attributes.

The corresponding CodeFixProvider, decorated with [ExportCodeFixProvider] attribute composes just fine. Code refactorings ([ExportCodeRefactoringProvider]) compose OK as well.

The VSIX manifets is the default one generated by the project template - the project output is declared as both Microsoft.VisualStudio.MefComponent and Microsoft.VisualStudio.Analyzer.

Both the export interface and the exported instance are located in the same assembly as the analyzer, but the situation is the same when I move the interface and exported instance into a new portable class library.

So my question is this: am I missing something regarding the composition workflow or is this a bug?


manishv wrote Dec 31, 2014 at 5:26 PM

Currently, this scenario is unsupported and is part of our backlog. We currently instantiate diagnostic analyzers using reflection. We have had multiple requests to enable this scenario, especially for VS IDE-only analyzers that require VS MEF exports.
As a workaround, you can try defining a MEF provider service in your assembly that participates in MEF composition and imports whatever services your analyzers are interested in. The analyzer can query this service for MEF imports.

mareklinka wrote Dec 31, 2014 at 6:11 PM

Ah, good to know it wasn't just my mind failing spectacularly, thanks for the info.

The proposed workaround sounds good, will try to go that way for now. Hope this gets resolved eventually, MEF is a great way to do this sort of stuff.

mareklinka wrote Feb 15, 2015 at 9:48 AM

I apologize for resurrecting a two-months-old thread (I've been dealing with other things in my project), but I wanted to share my workaround for this issue, in case others stumble across this.

In the end I decided to ditch MEF completely and go with a very simple "composition container" developed by jonathanpeppers over at GitHub:

I modified the original code a little, included a "TryResolve" method to allow safe object retrieval. What I do is register my settings provider at initialization (called from a VSIX package, no MEF) and then call TryResolve in my analyzers.