Ejemplo n.º 1
0
        /// <summary>Finds the best methods for the specified arguments given a candidate method enumeration.</summary>
        /// <param name="signatures">The candidate function signatures.</param>
        /// <param name="argumentTypes">The argument type references to match.</param>
        /// <returns>The number of "best match" methods.</returns>
        private static int FindBestSignature(FunctionSignature[] signatures, IEdmTypeReference[] argumentTypes)
        {
            Debug.Assert(signatures != null, "signatures != null");
            Debug.Assert(argumentTypes != null, "argumentTypes != null");
            Debug.Assert(argumentTypes.All(t => t == null || t.IsODataPrimitiveTypeKind()), "All argument types must be primitive or null.");
            Debug.Assert(signatures.All(s => s.ArgumentTypes != null && s.ArgumentTypes.All(t => t.IsODataPrimitiveTypeKind())), "All signatures must have only primitive argument types.");

            List<FunctionSignature> applicableSignatures = signatures.Where(signature => IsApplicable(signature, argumentTypes)).ToList();
            if (applicableSignatures.Count > 1)
            {
                applicableSignatures = FindBestApplicableSignatures(applicableSignatures, argumentTypes);
            }

            int result = applicableSignatures.Count;
            if (result == 1)
            {
                // TODO: deal with the situation that we started off with all non-open types
                //       and end up with all open types; see RequestQueryParser.FindBestMethod. 
                //       Ignored for now since we don't support open types yet.
                FunctionSignature signature = applicableSignatures[0];
                for (int i = 0; i < argumentTypes.Length; i++)
                {
                    argumentTypes[i] = signature.ArgumentTypes[i];
                }

                result = 1;
            }
            else if (result > 1)
            {
                // We may have the case for operators (which C# doesn't) in which we have a nullable operand
                // and a non-nullable operand. We choose to convert the one non-null operand to nullable in that
                // case (the binary expression will lift to null).
                if (argumentTypes.Length == 2 && result == 2)
                {
                    if (applicableSignatures[0].ArgumentTypes[0].Definition.IsEquivalentTo(applicableSignatures[1].ArgumentTypes[0].Definition))
                    {
                        FunctionSignature nullableMethod =
                            applicableSignatures[0].ArgumentTypes[0].IsNullable ?
                            applicableSignatures[0] :
                            applicableSignatures[1];
                        argumentTypes[0] = nullableMethod.ArgumentTypes[0];
                        argumentTypes[1] = nullableMethod.ArgumentTypes[1];

                        // TODO: why is this necessary? We keep it here for now since the product has it but assert
                        //       that nothing new was found.
                        int signatureCount = FindBestSignature(signatures, argumentTypes);
                        Debug.Assert(signatureCount == 1, "signatureCount == 1");
                        Debug.Assert(argumentTypes[0] == nullableMethod.ArgumentTypes[0], "argumentTypes[0] == nullableMethod.ArgumentTypes[0]");
                        Debug.Assert(argumentTypes[1] == nullableMethod.ArgumentTypes[1], "argumentTypes[1] == nullableMethod.ArgumentTypes[1]");
                        return signatureCount;
                    }
                }
            }

            return result;
        }