即使运行时检查 = true,程序集也不会被 ccrewriter 重写

Assembly is not rewritten by ccrewriter even though Runtime Checking = true

我有一个项目。在这个项目中,我使用 .NET 的代码合同。我设置运行时检查 = true。 。但是在运行时我有一个 ContractException:

Exception thrown: 'System.Diagnostics.Contracts.ContractException' in mscorlib.dll

Additional information: An assembly (probably "Common") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.Ensures and the CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild. CCRewrite can be downloaded from http://go.microsoft.com/fwlink/?LinkID=169180.

After the rewriter is installed, it can be enabled in Visual Studio from the project's Properties page on the Code Contracts pane. Ensure that "Perform Runtime Contract Checking" is enabled, which will define CONTRACTS_FULL The cause of the exception is not that condition doesn't fulfill, but that the assembly is not rewritten. Ccrewriter is installed, I don't have troubles with other projects.

发生的代码:

Contract.Ensures(_instance != null && _instance._authData != null);

此代码未被重写,因此它在过程开始时执行。

我知道有一个解决方法可以只使用 postbuild 事件来执行 ccrewrite,但我想避免它。

造成这种行为的原因是什么?如何检查 ccrewrite 是否被调用?我在构建输出中没有看到任何信息。

看起来这是 CC 中的一个错误。我发现了一个奇怪的解决方法:

我的项目的csproj文件是以前手工编辑的,所以它有signAssebly标签和codecontracts设置的部分:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
  <SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  <SignAssembly>false</SignAssembly>
  <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
  <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
  <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>

  ....

  <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
  <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
  <CodeContractsAnalysisWarningLevel>3</CodeContractsAnalysisWarningLevel>
  <RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>

所以我将 CodeContracts 设置移到了通常存储它的部分;

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  <PlatformTarget>AnyCPU</PlatformTarget>
  <DebugSymbols>true</DebugSymbols>
  <DebugType>full</DebugType>
  <Optimize>false</Optimize>
  <OutputPath>bin\Debug\</OutputPath>
  <DefineConstants>DEBUG;TRACE</DefineConstants>
  <ErrorReport>prompt</ErrorReport>
  <WarningLevel>4</WarningLevel>
  <Prefer32Bit>false</Prefer32Bit>
  <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
  <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
  <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>

  ....

  <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
  <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
</PropertyGroup

现在可以了。我认为放置部分的位置没有太大区别,它只对构建目标很重要。

如果有人能解释一下,为什么会这样,我会重新接受答案。