locked
Hand-generated contracts assembly? RRS feed

  • Question

  • Since the re-writer can't handle F# assemblies yet, I thought perhaps I might quickly hand-code a reference assembly. Are there any guidelines as to what should appear in it? Is this possible?
    Tuesday, July 5, 2011 3:26 AM

All replies

  • Fairly straightforward

    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    
    [assembly: AssemblyTitle("UnmanagedUtilities.Contracts")]
    [assembly: AssemblyDescription("UnmanagedUtilities.Contracts")]
    
    #pragma warning disable 0436 // we are supposed to mark our class with this attribute, but it's marked protected.
    [assembly: System.Diagnostics.Contracts.ContractReferenceAssembly()]
    [assembly: System.Diagnostics.Contracts.ContractDeclarativeAssembly()]
    #pragma warning restore 0436
    
    [assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)] // required for contracts
    
    namespace System.Diagnostics.Contracts
    {
      using System;
      using System.Runtime.CompilerServices;
    
      /// <summary>
      /// We have to declare contracts again in this assembly, bizarrely
      /// </summary>
      internal sealed class Contract
      {
        /// <summary>Redefine contract function</summary>
        public static void Requires(bool condition, string userSuppliedString, string sourceText)
        {
        }
    
        /// <summary>Redefine contract function</summary>
        public static void Ensures(bool condition, string userSuppliedString, string sourceText)
        {
        }
    
        /// <summary>Redefine contract function</summary>
        public static void Invariant(bool condition, string userSuppliedString, string sourceText)
        {
        }
    
        /// <summary>Redefine contract function</summary>
        /// <returns>Doesn't matter what it returns</returns>
        public static T Result<T>()
        {
          return default(T);
        }
    
        // ... and whatever else you use
      }
    
      /// <summary>Required to make a fake code contract file contracts work</summary>
      [CompilerGenerated]
      internal sealed class ContractDeclarativeAssemblyAttribute : Attribute
      {
      }
    
      /// <summary>Required to make a fake code contract file contracts work</summary>
      [CompilerGenerated]
      internal sealed class ContractReferenceAssemblyAttribute : Attribute
      {
      }
    
      //
      //
      // Then you must write your class again with EXACTLY the
      // the same names, including type parameters, including
      // just the contract statements, but not your code.
    }
    
    
    


    Tuesday, July 5, 2011 5:28 AM
  • Hi,

    When I tried this too it didn't work for me.  Is it actually working for you?  Perhaps I missed something in my implementation.

    Anyway, I've emailed the CC team requesting this feature and they are aware that "the current system of generating reference assemblies is not optimal" and "we have some ideas on how to improve it and make the experience better for all of us", which means it might not be safe to depend upon this implementation for future builds.

    - Dave


    http://davesexton.com/blog
    Tuesday, July 5, 2011 1:15 PM
  • It is working. The first thing was to get the assembly in the right place for contracts to believe it found the reference assembly. Then you have to make your contracted class EXACTLY the same as the original, and it has to reference the contract functions in your reference assembly, not the ones in mscorlib. Everything has to be in its original namespace, e.g. X.Y.Z's contract class is called X.Y.Z, and all the argument names have to be the same. You have to call the overloaded functions, like Requires(bool,string,string), not Requires(bool).
    Tuesday, July 5, 2011 3:06 PM