Data contracts

資料合約,Data contracts,Code Contracts

一般驗證value的輸入輸出,我們可以用以下傳統的方式

public void Initialize(string name, int id)
{
    if (string.IsNullOrEmpty(value))
        throw new ArgumentException("name");
    if (id < 0) 
        throw new ArgumentOutOfRangeException("id");
    // Do some work here.
}

而今天要介紹的Code Contract,可以將以上的寫法改的更為優雅,且功能更為強大。

寫法如下:

public void Initialize(string name, int id)
{
    Contract.Requires(!string.IsNullOrEmpty(name));
    Contract.Requires(id > 0);
    Contract.Ensures(Name == name);
    Contract.Ensures(Id == id);
}

在開始使用之前要先安裝 Code Contracts

開啟專案屬性

Code Contracts => Perform Runtime Contract Checking Custom Rewriter Methods 打勾

這樣就設置完成了。

 

接下來就開始介紹基本的兩個驗證

  • preconditions - Contract.Requires()

    • 在執行method程式碼之前做的驗證

  • postconditions - Contract.Ensures()

    • 在method執行結束後,做的驗證

以下程式範例,我限制傳入的數字要大於0的數字,且輸出一定要是傳入值的平方。

static void Main(string[] args)
{
    int value = SquareMath(0);
    Console.WriteLine(value);
}

private static int SquareMath(int value) 
{
    // preconditions            
    Contract.Requires(value > 0);
    
    // postconditions
    Contract.Ensures(Contract.Result<int>() == value * value);

    return value * value;
}

因為我傳入是0,所以以上面執行結果,我會得到一個錯誤訊息。

同理,如果我輸出不是 value * value,則一樣會跳出例外狀況。

知道Code Contracts的基本用法後,接下來就是要介紹如何針對interface 的 method做驗證,且所有實作該interface的類別,都有該驗證功能。

1.定義一個interface

2.新增一個abstract class 定義contract

3.使用ContractClassAttribute和 ContractClassForAttribute 將contract綁在一起

[ContractClass(typeof(MathContracts))]
public interface IMath
{
    int SquareMath(int value);        
}

[ContractClassFor(typeof(IMath))]
public abstract class MathContracts : IMath
{
    public int SquareMath(int value)
    {
        // 確保傳入數字大於0
        Contract.Requires(value > 0);
        
        // 確保輸出結果為輸入的平方
        Contract.Ensures(Contract.Result<int>() == value * value);

        throw new NotImplementedException();
    }
}

這樣所有實作IMath的類別,都有自動驗證的功能,如以下範例:

public class TestMath : IMath
{
    public int SquareMath(int value)
    {
        return value * 2;
    }
}

static void Main(string[] args)
{
    TestMath tm = new TestMath();
    int value = tm.SquareMath(50);

    Console.WriteLine(value);
}

我故意將輸出結果不是輸入的平方,因為Contract的關係,會幫我做輸出驗證,拋出Exception

且使用Contract的程式碼,可以自動產生xml document

可參考:http://weblogs.asp.net/gunnarpeipman/enabling-xml-documentation-for-code-contracts

 

以上為Code Contract 的基本介紹,其實Code Contract的功能非常強大,也算是必學的知識之ㄧ阿。

 

參考:

http://www.codeproject.com/Articles/103779/Introducing-Code-Contracts

http://www.codeproject.com/Articles/104707/Introducing-Code-Contracts-Part

 

 

一天一分享,身體好健康。

該追究的不是過去的原因,而是現在的目的。