2010-07-07 15 views
6

Estoy usando MS Code Contracts y me he encontrado con un inconveniente al usar la herencia de la interfaz y los atributos de ContractClassFor.Contratos de código: ¿cómo lidiar con interfaces heredadas?

Dadas estas interfaces y clases de contratos:

[ContractClass(typeof(IOneContract))] 
interface IOne { } 
[ContractClass(typeof(ITwoContract))] 
interface ITwo : IOne { } 

[ContractClassFor(typeof(IOne))] 
abstract class IOneContract : IOne { } 
[ContractClassFor(typeof(ITwo))] 
abstract class ITwoContract : IOneContract, ITwo { } 

Digamos que Ione y ITwo son interfaces sustanciales. Entonces, IOneContract tendría una cantidad significativa de código para las verificaciones necesarias.

No quiero duplicar todo eso en ITwoContract para las interfaces IOne. Solo quiero agregar nuevos contratos para las interfaces de TI. Heredar una clase de contrato de otra parece la forma más probable de reutilizar ese código. Sin embargo, me sale el siguiente error:

EXEC : warning CC1066: Class 'ITwoContract' is annotated as being the contract for the interface 'ITwo' and cannot have an explicit base class other than System.Object. 

¿Esto es una limitación en Contratos de código o lo estoy haciendo mal? Tenemos una gran cantidad de herencia de interfaz en nuestro proyecto y esto parece ser un factor decisivo para los Contratos de Código si no puedo encontrar la manera de solucionar este problema.

Respuesta

10

En lugar de:

[ContractClassFor(typeof(ITwo))] 
abstract class ITwoContract : IOneContract, ITwo { } 

Sólo heredan contrato:

[ContractClassFor(typeof(ITwo))] 
abstract class ITwoContract : ITwo { } 

Sólo es necesario para proporcionar los contratos sobre los métodos que son nuevos en ITwo. Los contratos de IOneContract se heredan de forma automática, y se puede declarar todos los IOne métodos heredados como abstracta — de hecho, se no puede ofrecer contratos para IOne en ITwoContract o CC se quejará :)

Por ejemplo, si tener esto:

[ContractClass(typeof (IOneContract))] 
interface IOne 
{ 
    int Thing { get; } 
} 

[ContractClass(typeof (ITwoContract))] 
interface ITwo : IOne 
{ 
    int Thing2 { get; } 
} 

[ContractClassFor(typeof (IOne))] 
abstract class IOneContract : IOne 
{ 
    public int Thing 
    { 
     get 
     { 
      Contract.Ensures(Contract.Result<int>() > 0); 
      return 0; 
     } 
    } 
} 

[ContractClassFor(typeof (ITwo))] 
abstract class ITwoContract : ITwo 
{ 
    public int Thing2 
    { 
     get 
     { 
      Contract.Ensures(Contract.Result<int>() > 0); 
      return 0; 
     } 
    } 

    public abstract int Thing { get; } 
} 

a continuación, esta aplicación va a decir "contrato no probada" en ambos métodos, como se esperaba:

class Two : ITwo 
{ 
    public int Thing 
    { 
     get { return 0; } 
    } 

    public int Thing2 
    { 
     get { return 0; } 
    } 
} 
+3

¡Ah! El "y usted puede declarar todos los métodos IOne heredados como abstractos" era la parte clave que me faltaba. Gracias. – scobi

+1

El problema es que todavía tiene que especificar todos los métodos de IOne en la clase de contrato abstracto ITwoContract. Si IOne tiene, por ejemplo, 50 métodos, necesito repetirlos para cada interfaz que herede de IOne: muy tedioso y hace que los cambios en IOne sean difíciles. – Rob

+1

Si tiene una interfaz con 50 métodos, probablemente encontrará todos los cambios relacionados con esa interfaz tediosos y duros porque violará el Principio de Responsabilidad Individual. –

Cuestiones relacionadas