2016-11-23 57 views
29

我剛剛安裝了新發布的Visual Studio 2017 Enterprise(RC)。但是,我無法使其與Microsoft CodeContracts合作。使用VS2015的CodeContract完全沒有問題。我錯過了什麼嗎?VS2017是否支持CodeContracts?

+0

請微軟的某人發表評論嗎? – user2106007

+0

任何人來自微軟VS隊? VS2017是否可以使用CodeContracts? – user2106007

+2

github上的官方問題[「CodeContracts not working in VS2017」#476](https://github.com/Microsoft/CodeContracts/issues/476)已打開,並且[Visual Studio 2017支持#451](https: //github.com/Microsoft/CodeContracts/issues/451) –

回答

12

在這個時候寫有對VS2017沒有合同的定義,但你可以避開它具有以下如果使用Nuget package DotNet.Contracts

  • 導航到CodeContracts NuGet包目錄(DotNet.Contracts.1.10.20606.1\MsBuild
  • 複製在v14.0文件夾
  • 其重命名爲v15.0

一切壽ld按預期構建。

+0

謝謝你的迴應。看起來我必須回到基本的...你如何在VS2015中使用CodeContracts nuget包?你是否需要安裝額外的組件(例如Contracts.devlab9ts.msi)? – user2106007

+0

沒有安裝Contracts.devlab9ts.msi,我沒有看到項目屬性中的「代碼合同」選項卡。 – user2106007

+0

user6706499 - 你是如何得到它的工作?你需要安裝Contracts.devlab9ts.msi嗎? – user2106007

6

目前還沒有版本的Code Contracts for .NET支持的Visual Studio 2017年。但是這個問題可以補救,如果下面的目標文件

C:\Program Files (x86)\MSBuild\4.0\Microsoft.Common.Targets\ImportAfter\CodeContractsAfter.targets 

複製到你的VS2017的MSBuild的ImportAfter位置:

C:\Program Files (x86)\Microsoft Visual Studio\2017\#YourVS2017Product#\MSBuild\15.0\Microsoft.Common.targets\ImportAfter 

注意:將#YourVS2017Product#替換爲上述路徑中的VS2017產品名稱,例如社區。

這將允許您使用VS2017中的代碼合同進行構建,但不會解決未在項目設置中顯示的CC選項卡問題。爲此,您仍然需要切換到VS2015。

+0

謝謝埃丁。這是否意味着所有的代碼合同功能都可以工作,如果一個項目已經被配置使用它? – user2106007

+0

是的,但我建議做一些測試以確保您的dll被CC重寫。 – Edin

+0

謝謝埃丁。考慮到微軟CC的未來不確定性,我們決定繼續前進,用微軟內部開發的CC框架取代微軟CC一週時間,以保留CC概念及其大部分功能。然而,我們真的錯過了界面合同 - 我相信你明白我的意思。 – user2106007

2

代碼合同並沒有在2017年VS工作的原因是:

  1. 代碼契約的MSBuild文件不會在MSBuild的文件VS 2017年樹導入(容易解決)
  2. 代碼合同配置UI中不存在VS 2017年項目屬性(容易固定由包括CodeContracts的MSBuild屬性)

當然關於CodeContracts的未來的問題是有效的,但你可以執行以下操作以啓用使用CodeCont現有項目racts打造VS 2017年:

  1. C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.Targets\ImportAfter\CodeContractsAfter.targets的內容添加到您的csproj文件(通過進口直接或間接)。最基本的方法是添加到您的csproj文件:

    <PropertyGroup> 
        <CodeContractsInstallDir Condition="'$(CodeContractsInstallDir)'==''">C:\Program Files (x86)\Microsoft\Contracts\</CodeContractsInstallDir> 
    </PropertyGroup> 
    <Import Condition="'$(CodeContractsImported)' != 'true' AND '$(DontImportCodeContracts)' != 'true'" Project="$(CodeContractsInstallDir)MsBuild\v$(VisualStudioVersion)\Microsoft.CodeContracts.targets" /> 
    

請注意,如果安裝CodeContracts第一的PropertyGroup不應該是必要的,B/C CodeContractsInstallDir應被指定爲一個環境變量。在這種情況下,只需將

<Import Condition="'$(CodeContractsImported)' != 'true' AND '$(DontImportCodeContracts)' != 'true'" Project="$(CodeContractsInstallDir)MsBuild\v$(VisualStudioVersion)\Microsoft.CodeContracts.targets" /> 

添加到* .csproj文件中即可。

  1. 指定*中的所有CodeContracts屬性。csproj文件(直接或間接通過導入)。例如:

    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    
    <!-- Code Contracts settings --> 
    <PropertyGroup> 
        <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode> 
        <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking> 
        <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> 
        <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure> 
        <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> 
        <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers> 
        <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis> 
        <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations> 
        <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations> 
        <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations> 
        <CodeContractsEnumObligations>False</CodeContractsEnumObligations> 
        <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions> 
        <CodeContractsInferRequires>False</CodeContractsInferRequires> 
        <CodeContractsInferEnsures>False</CodeContractsInferEnsures> 
        <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants> 
        <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions> 
        <CodeContractsSuggestRequires>True</CodeContractsSuggestRequires> 
        <CodeContractsSuggestEnsures>False</CodeContractsSuggestEnsures> 
        <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants> 
        <CodeContractsDisjunctiveRequires>False</CodeContractsDisjunctiveRequires> 
        <CodeContractsRunInBackground>True</CodeContractsRunInBackground> 
        <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies> 
        <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> 
        <CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs> 
        <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults> 
        <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> 
        <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly> 
        <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel> 
    </PropertyGroup> 
    
    <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> 
    </PropertyGroup> 
    
    <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> 
        <CodeContractsRuntimeCheckingLevel>ReleaseRequires</CodeContractsRuntimeCheckingLevel> 
    </PropertyGroup> 
    
    </Project> 
    

如果你有以上幾個項目的更多,我建議在私人NuGet包把這些和引用該NuGet包中的每個項目。代碼合同設置(來自步驟2)可以放入mycompany.codecontracts.props文件中,代碼合同目標(來自步驟1)可以放入mycompany.codecontracts.targets文件中。 https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package#including-msbuild-props-and-targets-in-a-package

我願意提供在GitHub上一個例子,如果有足夠的興趣:在包裝上的MSBuild特性的NuGet包這裏/目標

更多信息。

+2

只是未來的小費;要在子彈點內編碼塊文本,需要按8個空格縮進,而不是通常的四個 – Rob

+0

謝謝!我試圖找出爲什麼它不起作用。 – crimbo

+0

@crimbo:感謝您的詳細解答。在編譯過程中放置​​這些東西似乎沒有什麼問題,但它似乎也不能正確執行CCRewrite。因此,在運行時,出現以下錯誤: 「必須使用代碼合同二進制重寫器(CCRewrite)重新編寫彙編(可能爲」...「),因爲它調用Contract.Requires 並定義了CONTRACTS_FULL符號。 這是預期嗎?在Visual Studio 2017中是否有支持CCRewrite的場景? –

1

我發現這裏提出的方法並不簡單,特別是它需要每個開發人員的機器和構建服務器上的更改。

我決定創建自己的非常簡化版本的Contract.Requires(),將需要全球唯一在主叫類取代using聲明。

using MYCommon.Diagnostics; //System.Diagnostics.Contracts; 

當/如果System.Diagnostics.Contractswill be available for VS 2017和.NetStandard,它會很容易恢復到正確的版本。

實際的類是:

/// <summary> 
    /// Contract.Requires(config != null); in VS 2017 not throw ArgumentNullException 
    /// The class is workaround for https://stackoverflow.com/questions/40767941/does-vs2017-work-with-codecontracts 
    /// </summary> 
    public class Contract 
    { 
     public static void Requires(bool condition, string message = null) 
     { 
      Requires<ArgumentNullException>(condition, message); 
     } 
     public static void Requires<TException>(bool condition, string message=null) where TException:Exception , new() 
     { 
      if (!condition) 
      { 
       //https://stackoverflow.com/questions/41397/asking-a-generic-method-to-throw-specific-exception-type-on-fail/41450#41450 
       var e=default(TException); 
       try 
       { 
        message = message ?? "Unexpected Condition"; //TODO consider to pass condition as lambda expression 
        e = Activator.CreateInstance(typeof(TException), message) as TException; 
       } 
       catch (MissingMethodException ex) 
       { 
        e = new TException(); 
       } 
       throw e; 
      } 
     } 
    } 

基本限制是典型的使用Contract.Requires(param1!=null);不允許我拋出異常與參數的名稱,以及更好的使用是有點長:

Contract.Requires<ArgumentNullException>(param1!=null, "param1 is null"); 
+1

如果您主要關心的是Requires()'的運行時驗證,則這是一種有效的策略。並且可以擴展以支持'Assert()','Assume()','Exists()'和'ForAll()'。但是,如果它們是必需的,那麼使用這種方法來支持'Ensures()','Invariant()','Result()'或'ValueAtReturn()'將是不切實際的(沒有重要的調用者重構)。換句話說,這隻能作爲驗證前提條件的簡寫。 –

8

正如其他人指出,微軟並沒有優先代碼契約及其long-term support remains unclear(雖然有已經已經通過羅斯林一些ongoing discussion about language-level integration)。

截至March 11th, 2017,然而,社區貢獻者Yaakov已經,至少,更新source code到包括Visual Studio 2017 build targets(謝謝!)。該版本支持編譯期間的靜態檢查以及使用CCRewrite的運行時驗證。

Note: This build does not provide configuration support via the project's properties pane . As such, code contracts will need to be configured by manually adding the appropriate properties to the csproj file. See @crimbo's answer above for a comprehensive list of properties .

不幸的是,雖然這些更新已合併到主代碼分支,他們既沒有反映在Marketplace distribution或官方NuGet Package。因此,您需要從存儲庫下載並編譯source code(這很簡單;只需使用提供的BuildCC.bat文件)。

Important: The static analysis for Code Contracts has a hard-coded dependency on .NET 3.5, which is no longer installed by default in either Windows 10 or Visual Studio 2017. As such, you'll want to ensure this "feature" is enabled (or download it separately); otherwise, you'll get a compile-time error.

另外,爲June 15th, 2017Igor Bek已在他的NuGet Package此更新,所以最簡單的方法是簡單地添加「CodeContracts。的MSBuild」你packages.config通過:

Install-Package CodeContracts.MSBuild -Version 1.9.10714.3 

Background: Igor Bek first put this package together as a proof-of-concept for the Code Contracts team , and it was later the basis for the official NuGet package (in v1.10.10126.2). Since Microsoft hasn't updated the official NuGet package, his is now the most up-to-date.

鑑於支持目前的狀態,我不鼓勵人們採用新的項目代碼的合同,但這應該提供的是已經投入開發的向後兼容性轉換爲現有.NET Framework項目的代碼合同。