Я использую Контракты Кода MS и столкнулся с препятствием с использованием интерфейсного наследования и атрибутов ContractClassFor.
Учитывая эти интерфейсы и классы контракта:
[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 { }
Скажем, это IOne и ITwo является существенными интерфейсами. Таким образом, IOneContract имел бы существенный объем кода в нем для необходимых проверок.
Я не хочу копировать все это в ITwoContract для интерфейсов IOne. Я только хочу добавить новые контракты для интерфейсов ITwo. Наследование одного класса контракта от другого кажется вероятным способом снова использовать тот код. Все же я получаю следующую ошибку:
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.
Действительно ли это - ограничение в Контрактах Кода, или я делаю его неправильно? У нас есть большое интерфейсное наследование в нашем проекте, и это чувствует себя подобно недопустимому для Контрактов Кода, если я не могу выяснить, как работать вокруг этой проблемы.
Вместо:
[ContractClassFor(typeof(ITwo))]
abstract class ITwoContract : IOneContract, ITwo { }
Просто наследуйте контракт:
[ContractClassFor(typeof(ITwo))]
abstract class ITwoContract : ITwo { }
Вам нужно предоставить контракты только на методы, которые являются новыми в ITwo
. Контракты из IOneContract
будут наследоваться автоматически, и вы можете объявить все наследуемые методы IOne
абстрактными - на самом деле, вы не можете предоставить контракты для IOne
на ITwoContract
, иначе CC будет жаловаться: )
Например, если у вас есть это:
[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; }
}
Тогда эта реализация скажет "unproven contract" на обоих методах, как и ожидалось:
class Two : ITwo
{
public int Thing
{
get { return 0; }
}
public int Thing2
{
get { return 0; }
}
}