/// <summary> /// Bind a parameter alias which is inside another alias value. /// </summary> /// <param name="bindingState">The alias name which is inside another alias value.</param> /// <param name="aliasToken">The cache of alias value nodes</param> /// <returns>The semantics node tree for alias (the @p1 in "@p1=...", not alias value expression)</returns> internal ParameterAliasNode BindParameterAlias(BindingState bindingState, FunctionParameterAliasToken aliasToken) { ExceptionUtils.CheckArgumentNotNull(bindingState, "bindingState"); ExceptionUtils.CheckArgumentNotNull(aliasToken, "aliasToken"); string alias = aliasToken.Alias; ParameterAliasValueAccessor aliasValueAccessor = bindingState.Configuration.ParameterAliasValueAccessor; if (aliasValueAccessor == null) { return(new ParameterAliasNode(alias, null)); } // in cache? SingleValueNode aliasValueNode = null; if (!aliasValueAccessor.ParameterAliasValueNodesCached.TryGetValue(alias, out aliasValueNode)) { // has value expression? string aliasValueExpression = aliasValueAccessor.GetAliasValueExpression(alias); if (aliasValueExpression == null) { aliasValueAccessor.ParameterAliasValueNodesCached[alias] = null; } else { aliasValueNode = this.ParseAndBindParameterAliasValueExpression(bindingState, aliasValueExpression, aliasToken.ExpectedParameterType); aliasValueAccessor.ParameterAliasValueNodesCached[alias] = aliasValueNode; } } return(new ParameterAliasNode(alias, aliasValueNode.GetEdmTypeReference())); }
/// <summary> /// Bind path segment's operation or operationImport's parameters. /// </summary> /// <param name="configuration">The ODataUriParserConfiguration.</param> /// <param name="functionOrOpertion">The function or operation.</param> /// <param name="segmentParameterTokens">The parameter tokens to be binded.</param> /// <returns>The binded semantic nodes.</returns> internal static List <OperationSegmentParameter> BindSegmentParameters(ODataUriParserConfiguration configuration, IEdmOperation functionOrOpertion, ICollection <FunctionParameterToken> segmentParameterTokens) { // TODO: HandleComplexOrCollectionParameterValueIfExists is temp work around for single copmlex or colleciton type, it can't handle nested complex or collection value. ICollection <FunctionParameterToken> parametersParsed = FunctionCallBinder.HandleComplexOrCollectionParameterValueIfExists(configuration.Model, functionOrOpertion, segmentParameterTokens, configuration.Resolver.EnableCaseInsensitive, configuration.EnableUriTemplateParsing); // Bind it to metadata BindingState state = new BindingState(configuration); state.ImplicitRangeVariable = null; state.RangeVariables.Clear(); MetadataBinder binder = new MetadataBinder(state); List <OperationSegmentParameter> boundParameters = new List <OperationSegmentParameter>(); IDictionary <string, SingleValueNode> input = new Dictionary <string, SingleValueNode>(StringComparer.Ordinal); foreach (FunctionParameterToken paraToken in parametersParsed) { // TODO: considering another better exception if (paraToken.ValueToken is EndPathToken) { throw new ODataException(Strings.MetadataBinder_ParameterNotInScope( string.Format(CultureInfo.InvariantCulture, "{0}={1}", paraToken.ParameterName, (paraToken.ValueToken as EndPathToken).Identifier))); } SingleValueNode boundNode = (SingleValueNode)binder.Bind(paraToken.ValueToken); if (!input.ContainsKey(paraToken.ParameterName)) { input.Add(paraToken.ParameterName, boundNode); } } IDictionary <IEdmOperationParameter, SingleValueNode> result = configuration.Resolver.ResolveOperationParameters(functionOrOpertion, input); foreach (KeyValuePair <IEdmOperationParameter, SingleValueNode> item in result) { SingleValueNode boundNode = item.Value; // ensure node type is compatible with parameter type. IEdmTypeReference sourceTypeReference = boundNode.GetEdmTypeReference(); bool sourceIsNullOrOpenType = (sourceTypeReference == null); if (!sourceIsNullOrOpenType) { // if the node has been rewritten, no further conversion is needed. if (!TryRewriteIntegralConstantNode(ref boundNode, item.Key.Type)) { boundNode = MetadataBindingUtils.ConvertToTypeIfNeeded(boundNode, item.Key.Type); } } OperationSegmentParameter boundParamer = new OperationSegmentParameter(item.Key.Name, boundNode); boundParameters.Add(boundParamer); } return(boundParameters); }
/// <summary> /// Bind the expression of the LambdaToken /// </summary> /// <param name="queryToken">the expression token</param> /// <returns>the bound expression node</returns> private SingleValueNode BindExpressionToken(QueryToken queryToken) { SingleValueNode expression = this.bindMethod(queryToken) as SingleValueNode; if (expression == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_AnyAllExpressionNotSingleValue); } // type reference is allowed to be null for open properties. IEdmTypeReference expressionTypeReference = expression.GetEdmTypeReference(); if (expressionTypeReference != null && !expressionTypeReference.AsPrimitive().IsBoolean()) { throw new ODataException(ODataErrorStrings.MetadataBinder_AnyAllExpressionNotSingleValue); } return(expression); }