程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 利用.NET Code Contracts實現運行時驗證,.netcontracts

利用.NET Code Contracts實現運行時驗證,.netcontracts

編輯:C#入門知識

利用.NET Code Contracts實現運行時驗證,.netcontracts


.NET的Contract類庫是Declarative Programming實踐的一部分,可以對日常編程帶來很多好處:

  • 提高代碼可讀性,使用者一看Require, Ensure就知道這方法接受什麼輸入,產生什麼輸出。
  • 減少重復的驗證代碼
  • 配合第三方工具,可以方便靜態代碼分析和單元測試,方便產生API文檔,這些功能可以參見Code Contract主頁

Contract類本身已經在.NET 4.0之後集成進了System.Diagnostics.Contracts命名空間,但如果想使用Contract方法實現運行時的驗證,還需要單獨安裝一個VS插件。裝好之後,去項目屬性裡開啟運行時檢查:

這樣每次編譯項目的時候,插件裡的ccrewrite工具會將Contract方法編譯成有效的檢查代碼分別注入函數體的首尾。所以即使你把Contract.Ensures檢查放在函數開頭部分(這也是推薦做法),編譯之後這部分邏輯依然會出現在函數末尾,檢查函數結束條件是否滿足。

需要注意的是,如果想要在Debug和Release Build都使用運行時驗證功能,則需要在項目設置為Debug和Release編譯時,分別設置打開Runtime check。

Contract的基本使用包括Requires和Ensures,Requires在方法開始時檢查初始條件是否滿足,通常用來做參數驗證。Ensures方法用來在方法結束時檢查執行結果是否符合預期,比如可以放在Property set方法的末尾檢查Property是否被正確設置。

當檢查失敗時,默認會拋出ContractException,使用泛型的Requires和EnsuresOnThrow可以指定其他類型的異常。

        public async void GetPage(string entryPageUrl)
        {
            Contract.Requires<ArgumentException>(Uri.IsWellFormedUriString(entryPageUrl, UriKind.Absolute));
            ...
        }

 

Contract有一個很酷的feature,就是可以在接口裡定義一些檢查,要求所有的實現都滿足這些檢查條,這樣就不用在接口的每個實現裡分別定義相同的檢查邏輯了,非常的優雅,也符合Declaration Programming的初衷。

以下是示例代碼:

    [ContractClass(typeof(IBookRepositoryContract))]
    public interface IBookRepository
    {
        string BookTitle { get; set; }
        void Create(string name, Stream blob);
    }

    [ContractClassFor(typeof(IBookRepository))]
    sealed class IBookRepositoryContract : IBookRepository
    {
        public string BookTitle
        {
            get
            {
                return null;
            }
            set
            {
                Contract.Requires(!string.IsNullOrWhiteSpace(value), "Book title must not be empty.");
                Contract.Requires(string.IsNullOrWhiteSpace(this.BookTitle), "Book title has already been set.");
            }
        }

        public void Create(string name, Stream blob)
        {
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(this.BookTitle), "Book title hasn't been set");
        }
    }

這樣所有IBookRepository的實現類都無需再定義這些檢查了。

 

參考資料:

http://research.microsoft.com/en-us/projects/contracts/userdoc.pdf

http://blog.csdn.net/atfield/article/details/4465227

http://www.cnblogs.com/yangecnu/p/The-evolution-of-argument-validation-in-DotNet.html

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved