0

I am implementing the System.IServiceProvider.GetService method and I cannot suppress the warning ... implements interface method 'System.IServiceProvider.GetService(System.Type)', thus cannot add Requires.

[SuppressMessage("Microsoft.Contracts","CC1033", Justification="Check to require service type not null cannot be applied")]
public object GetService(Type serviceType)
{
}
Mightymuke
  • 5,094
  • 2
  • 31
  • 42
Arthur Greef
  • 319
  • 1
  • 9

1 Answers1

0

I'm guessing GetService is a method in an interface that you've implemented in a concrete class, and that the method in the concrete class contains a contract. This contracts needs to be moved to a contract class that provides the contracts for the interface. Full details can be found in the code contracts documentation (in section 2.8). The following is an extract:

Since most languages/compilers (including C# and VB) will not let you put method bodies within an interface, writing contracts for interface methods requires creating a separate contract class to hold them.

The interface and its contract class are linked via a pair of attributes (Section 4.1).

[ContractClass(typeof(IFooContract))]
interface IFoo
{
    int Count { get; }
    void Put(int value);
}

[ContractClassFor(typeof(IFoo))]
abstract class IFooContract : IFoo
{
    int IFoo.Count
    {
        get
        {
            Contract.Ensures( 0 <= Contract.Result<int>() );
            return default( int ); // dummy return
        }
    }
    void IFoo.Put(int value)
    {
        Contract.Requires( 0 <= value );
    }
}

If you prefer to not do this, then to suppress the warning simply remove the code contract as it isn't being applied anyway.

UPDATE

This is a test case that seems to be working.

namespace StackOverflow.ContractTest
{
    using System;
    using System.Diagnostics.Contracts;

    public class Class1 : IServiceProvider
    {
        public object GetService(Type serviceType)
        {
            Contract.Requires<ArgumentNullException>(
                serviceType != null,
                "serviceType");
            return new object();
        }
    }
}

namespace StackOverflow.ContractTest
{
    using System;

    using NUnit.Framework;

    [TestFixture]
    public class Tests
    {
        [Test]
        public void Class1_Contracts_AreEnforced()
        {
            var item = new Class1();
            Assert.Throws(
                Is.InstanceOf<ArgumentNullException>()
                    .And.Message.EqualTo("Precondition failed: serviceType != null  serviceType\r\nParameter name: serviceType"),
                () => item.GetService(null));
        }
    }
}

Is this doing something different to your scenario?

Community
  • 1
  • 1
Mightymuke
  • 5,094
  • 2
  • 31
  • 42
  • The interface is provided by the Dot Net Framework so I do not think I can take the approach of adding a contract class. – Arthur Greef Jan 03 '13 at 23:14
  • What version code contracts are you using, and do you have a repro? I'll update my answer shortly with a test case that's working for me, but looks like I might be missing something. – Mightymuke Jan 03 '13 at 23:45