Question

I am trying to define code contracts for an interface using ContractClass and ContractClassFor. It works fine when everything is in the same assembly, but if I put the interface definition and its respective contract class in a different assembly then the concrete class implementation, it doesn't work anymore.

For example, this code works:

namespace DummyProject
{
    [ContractClass(typeof(AccountContracts))]
    public interface IAccount
    {
        void Deposit(double amount);
    }

    [ContractClassFor(typeof(IAccount))]
    internal abstract class AccountContracts : IAccount
    {
        void IAccount.Deposit(double amount)
        {
            Contract.Requires(amount >= 0);
        }
    }

    internal class Account : IAccount
    {
        public void Deposit(double amount)
        {
            Console.WriteLine(amount);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Account account = new Account();
            // Contract.Requires will be checked below
            account.Deposit(-1);
        }
    }
}

Now, if I have a separate project with the following:

namespace SeparateAssembly
{
    [ContractClass(typeof(SeparateAssemblyAccountContracts))]
    public interface ISeparateAssemblyAccount
    {
        void Deposit(double amount);
    }

    [ContractClassFor(typeof(ISeparateAssemblyAccount))]
    internal abstract class SeparateAssemblyAccountContracts 
        : ISeparateAssemblyAccount
    {
        void ISeparateAssemblyAccount.Deposit(double amount)
        {
            Contract.Requires(amount >= 0);
        }
    }
}

and then in the main project (different assembly from the above) if I write:

namespace DummyProject
{
    internal class AccountFromSeparateAssembly 
        : ISeparateAssemblyAccount
    {
        public void Deposit(double amount)
        {
            Console.WriteLine(amount);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ISeparateAssemblyAccount accountFromSeparateAssembly = 
                    new AccountFromSeparateAssembly();

            // Neither of the two statements below will work
            // Contract.Requires will be ignored
            accountFromSeparateAssembly.Deposit(-1);

            ((AccountFromSeparateAssembly)accountFromSeparateAssembly).Deposit(-1);
        }
    }
}

Then the Contract.Requires is no longer checked in the Deposit method.

Any ideas on this, please? Thanks a lot!

Was it helpful?

Solution

I managed to make it work by choosing Contract Reference Assembly = Build in the Code Contracts settings of the project containing ISeparateAssemblyAccount and SeparateAssemblyAccountContracts.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top