/// <summary>
        /// Returns the method contract, if any, that has been associated with the given object. Returns null if no association exits.
        /// </summary>
        /// <param name="method">An object that might have been associated with a method contract. This can be any kind of object.</param>
        /// <returns></returns>
        public IMethodContract /*?*/ GetMethodContractFor(object method)
        {
            var cachedContract = this.contractProviderCache.GetMethodContractFor(method);

            if (cachedContract != null)
            {
                return(cachedContract == ContractDummy.MethodContract ? null : cachedContract);
            }

            IMethodReference methodReference = method as IMethodReference;

            if (methodReference == null)
            {
                this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract);
                return(null);
            }
            IMethodDefinition methodDefinition = methodReference.ResolvedMethod;

            if (methodDefinition is Dummy)
            {
                this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract);
                return(null);
            }
            var underlyingContract = this.underlyingContractProvider.GetMethodContractFor(method);

            if (!methodDefinition.IsAbstract)
            {
                if (underlyingContract != null)
                {
                    return(underlyingContract);
                }
                else
                {
                    this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract);
                    return(null);
                }
            }

            // The method is definitely an abstract method, so either:
            //  (a) we've never looked for a contract for it before, or else
            //  (b) it is a specialized/instantiated method and the uninstantiated version has already
            //      had its contract extracted.

            var unspecializedMethodDefinition = ContractHelper.UninstantiateAndUnspecializeMethodDefinition(methodDefinition);

            cachedContract = this.contractProviderCache.GetMethodContractFor(unspecializedMethodDefinition);

            if (cachedContract == null) // (a)

            // Check to see if its containing type points to a class holding the contract
            {
                IMethodDefinition /*?*/ proxyMethod = ContractHelper.GetMethodFromContractClass(this.host, unspecializedMethodDefinition);
                if (proxyMethod == null)
                {
                    this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract);
                    return(null);
                }
                MethodContract cumulativeContract = new MethodContract();
                if (underlyingContract != null)
                {
                    ContractHelper.AddMethodContract(cumulativeContract, underlyingContract);
                }

                IMethodContract proxyContract = this.underlyingContractProvider.GetMethodContractFor(proxyMethod);
                ITypeReference  contractClass = proxyMethod.ContainingTypeDefinition;
                var             gtir          = contractClass as IGenericTypeInstanceReference;
                if (gtir != null)
                {
                    contractClass = gtir.GenericType;
                }

                if (proxyContract == null)
                {
                    if (underlyingContract == null)
                    {
                        // then there was nothing on the abstract method (like purity markings)
                        this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract);
                        return(null);
                    }
                    else
                    {
                        // nothing on proxy, but something on abstract method
                        this.contractProviderCache.AssociateMethodWithContract(method, cumulativeContract);
                        return(cumulativeContract);
                    }
                }
                var copier = new CodeAndContractDeepCopier(this.host);
                proxyContract = copier.Copy(proxyContract);

                var cccc = new ConvertContractClassContract(this.host, contractClass, unspecializedMethodDefinition.ContainingType);
                proxyContract = cccc.Rewrite(proxyContract);
                proxyContract = ContractHelper.CopyContractIntoNewContext(this.host, proxyContract, unspecializedMethodDefinition, proxyMethod);

                ContractHelper.AddMethodContract(cumulativeContract, proxyContract);

                // Cache the unspecialized contract: specialize and instantiate on demand
                this.contractProviderCache.AssociateMethodWithContract(unspecializedMethodDefinition, cumulativeContract);
                cachedContract = cumulativeContract;
            }

            if (unspecializedMethodDefinition == methodDefinition)
            {
                return(cachedContract == ContractDummy.MethodContract ? null : cachedContract);
            }
            else // (b)
            {
                var mc = ContractHelper.InstantiateAndSpecializeContract(this.host, cachedContract, methodDefinition, unspecializedMethodDefinition);
                mc = (MethodContract)ContractHelper.CopyContractIntoNewContext(this.host, mc, methodDefinition, unspecializedMethodDefinition);
                return(mc);
            }
        }