Logo UGIdotNET

Definire Code Contract per una interfaccia (generica)

La versione 4.0 del framework permette di definire dei code contract sia per i membri di una classe, sia il contratto predefinito per una interfaccia mediante una serie di attributi. Parametrizzando opportunamente tali attributi, l'interfaccia può anche essere generica.

Si supponga di definire l'interfaccia IRepository<T> opportunamente decorata:

[ContractClass(typeof(RepositoryContract<>))]
public interface IRepository<T>
{
    void Add(T item);
}

L'attributo ContractClass permette di specificare quale sia la classe che denifisce il contratto di default per tutte le implementazioni di IRepository. Si noti che nella parametrizzazione dell'attributo l'interfaccia è specificata come tipo generico, ma senza l'alias del tipo.

Per implementare il contratto, è sufficiente definire una classe che:
  • Sia decorata con l'attributo ContractClassFor
  • Implementi l'interfaccia IRepository
In sintesi:

[ContractClassFor(typeof(IRepository<>))]
public class RepositoryContract<T> : IRepository<T>
{
    public void Add(T item)
    {
        Contract.Requires<ArgumentNullException>(item != null, "item");
    }
}

E' quindi ora possibile implementare una versione della classe Repository<T> in grado di trarre vantaggio dal suddetto contratto:

public class Repository<T> : IRepository<T>
{
    public void Add(T item)
    {
       //codice applicativo     }
}

Per verificare l'effettivo funzionamento del contratto, è sufficiente definire il seguente test:

[TestMethod()]
[ExpectedException(typeof(ArgumentNullException))]
public void Repository_Add_Should_Throw_On_Null_Valued_Object()
{
    Repository<Organization> repo = new Repository<Organization>();
    repo.Add(null);
}

Technorati tags: 
Autore: Andrea Saltarello
Data: 03 giugno 2010
Ultimo aggiornamento: 03 giugno 2010
Categorie:  C#
Tag:  code contracts design by contract c#

© 2001 User Group Italiano UGIdotNET. Tutti i diritti riservati. Note legali. - Partita IVA 01927050185