Using Microsoft.Bcl.Async with Code Analysis cause

2019-02-02 05:45发布

问题:

I'm trying to use Microsoft.Bcl.Async and Code Analysis, but when I run Code Analysis I get one or more errors.

I'm using Visual Studio 2012 with Update 2.

This is easy for me to reproduce:

  1. Create a new default Console App that targets .Net 4.
  2. Right click References then select Manage NuGet Packages...
  3. Click Online and type async into the Search Online box.
  4. You should see Async for .Net Framework 4 .... Click Install and accept all questions.
  5. Add to Main() a line that says: TaskEx.Delay(1000); and a using System.Threading.Tasks;
  6. Go to project properties, Code Analysis section and tick Enable Code Analysis on Build.
  7. Compile the program.

I get two Code Analysis errors:

CA0052 Error Running Code Analysis CA0052 : No targets were selected. [Errors and Warnings] (Global)

CA0055 Error Running Code Analysis CA0055 : Could not load ConsoleApplication2.exe. The following error was encountered while reading module 'ConsoleApplication2': Could not resolve member reference: [Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]System.Threading.Tasks.TaskEx::Delay. [Errors and Warnings] (Global)

I get different code analysis errors for other test programs. A basic Windows Forms app I tried gives me:

CA0001 Error Running Code Analysis CA0001 : The following error was encountered while reading module 'AsyncForNet4': Could not resolve member reference: [Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]System.Threading.Tasks.TaskEx::Delay. [Errors and Warnings] (Global)

Two questions:

  1. Can anyone else reproduce this problem?
  2. Does anyone have a solution for it?

回答1:

As mentioned by Nicole, this occurs because Code Analysis/FxCop is enforcing that strong names including versions match exactly. This behavior makes sense for .NET Framework, until you start to factor in binding redirects (or other platforms such as Store, Phone & Silverlight which always allow later versions of an assembly to match an earlier version), which FxCop does not respect.

I wrote this original behavior in FxCop, and it was over optimizing for correctness vs real world. At the time, we didn't have an opt out other than via the App.Config. However, luckily after I left the team, some smart person on the team added one both via the command-line and within Visual Studio.

Via the command-line:

FxCopCmd.exe /assemblycomparemode:StrongNameIgnoringVersion ...

Via Visual Studio:

  1. Right-click on the project in Solution Explorer and choose Unload
  2. Right-click on the project in Solution Explorer and choose Edit
  3. Within the first <PropertyGroup> element, add the following: <CodeAnalysisAdditionalOptions> /assemblycomparemode:StrongNameIgnoringVersion</CodeAnalysisAdditionalOptions>
  4. Right-click on the project in Solution Explorer, choose Reload saving the changes when prompted.

This will only work in Visual Studio 2012 and higher.



回答2:

This happens because the versions of the dependencies declared in Bcl.Async assemblies don't match those available at analysis time. The simplest workaround is to adjust FxCop's AssemblyReferenceResolveMode as described at http://davesbox.com/archive/2008/06/14/reference-resolutions-changes-in-code-analysis-and-fxcop-part-2.aspx.



回答3:

Having the same problem, and looking for a solution. The only mention I've found is in the comments of the bcl blog post - Microsoft.Bcl.Async is Now Stable (page 3 of comments) where Immo Landwerth's response to someone having the same issue is;

We're looking into it. At first glance it seems like a unification issue in the VS static code analysis feature (FxCop). We've contacted the owners of it. Unfortunately, I don't think there is a workaround other than disabling code analysis for those projects :-(

The response is dated 26th April 2013, whether there have been any developments since then.

So for now I guess the workarounds are:

  • Disable code analysis
  • Rewrite your code not to use TaskEx.Delay()