/// <summary> /// Validate the arguments to either isof or cast /// </summary> /// <param name="state">the current state of the binding algorithm</param> /// <param name="isCast">flag to indicate which function we're validating</param> /// <param name="args">the list of arguments, which could be changed</param> /// <returns>the return type of the function.</returns> private static IEdmTypeReference ValidateIsOfOrCast(BindingState state, bool isCast, ref List <QueryNode> args) { if (args.Count != 1 && args.Count != 2) { throw new ODataErrorException( ODataErrorStrings.MetadataBinder_CastOrIsOfExpressionWithWrongNumberOfOperands(args.Count)); } ConstantNode typeArgument = args.Last() as ConstantNode; IEdmTypeReference returnType = null; if (typeArgument != null) { returnType = TryGetTypeReference(state.Model, typeArgument.Value as string, state.Configuration.Resolver); } if (returnType == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_CastOrIsOfFunctionWithoutATypeArgument); } if (returnType.IsCollection()) { throw new ODataException(ODataErrorStrings.MetadataBinder_CastOrIsOfCollectionsNotSupported); } // if we only have one argument, then add the implicit range variable as the first argument. if (args.Count == 1) { args = new List <QueryNode>() { new EntityRangeVariableReferenceNode( state.ImplicitRangeVariable.Name, state.ImplicitRangeVariable as EntityRangeVariable), args[0] }; } else if (!(args[0] is SingleValueNode)) { throw new ODataException(ODataErrorStrings.MetadataBinder_CastOrIsOfCollectionsNotSupported); } if (isCast && (args.Count == 2)) { // throw if cast enum to not-string : if ((args[0].GetEdmTypeReference() is IEdmEnumTypeReference) && !string.Equals(typeArgument.Value as string, Microsoft.OData.Core.Metadata.EdmConstants.EdmStringTypeName, StringComparison.Ordinal)) { throw new ODataException(ODataErrorStrings.CastBinder_EnumOnlyCastToOrFromString); } // throw if cast not-string to enum : while (returnType is IEdmEnumTypeReference) { IEdmTypeReference edmTypeReference = args[0].GetEdmTypeReference(); if (edmTypeReference == null) { // Support cast null to enum break; } IEdmPrimitiveTypeReference referenceTmp = edmTypeReference as IEdmPrimitiveTypeReference; if (referenceTmp != null) { IEdmPrimitiveType typeTmp = referenceTmp.Definition as IEdmPrimitiveType; if ((typeTmp != null) && (typeTmp.PrimitiveKind == EdmPrimitiveTypeKind.String)) { break; } } throw new ODataException(ODataErrorStrings.CastBinder_EnumOnlyCastToOrFromString); } } if (isCast) { return(returnType); } else { return(EdmCoreModel.Instance.GetBoolean(true)); } }