private static ODataExpression ParseMemberExpression(Expression expression, string memberNames = null) { var memberExpression = expression as MemberExpression; if (memberExpression.Expression == null) { return(new ODataExpression(EvaluateStaticMember(memberExpression))); } // NOTE: Can't support ITypeCache here as we might be dealing with dynamic types/expressions var memberName = memberExpression.Member.GetMappedName(); memberNames = memberNames == null ? memberName : string.Join(".", memberName, memberNames); switch (memberExpression.Expression.NodeType) { case ExpressionType.Parameter: return(FromReference(memberNames)); case ExpressionType.Constant: return(ParseConstantExpression(memberExpression.Expression, memberNames)); case ExpressionType.MemberAccess: if (FunctionMapping.ContainsFunction(memberName, 0)) { return(FromFunction(memberName, ParseMemberExpression(memberExpression.Expression), new List <object>())); } else { return(ParseMemberExpression(memberExpression.Expression as MemberExpression, memberNames)); } default: throw Utils.NotSupportedExpression(expression); } }
private string FormatMappedFunction(ExpressionContext context, FunctionMapping mapping) { var mappedFunction = mapping.FunctionMapper( Function.FunctionName, functionCaller, Function.Arguments).Function; var formattedArguments = string.Join(",", (IEnumerable <object>)mappedFunction.Arguments.Select(x => FormatExpression(x, context))); return($"{mappedFunction.FunctionName}({formattedArguments})"); }
private static FunctionDefinition CreateFunctionDefinition(string functionName, int argumentCount, string mappedFunctionName, Func <FunctionDefinition, Func <string, ODataExpression, IEnumerable <object>, ODataExpression> > mapper, AdapterVersion adapterVersion = AdapterVersion.Any) { var functionCall = new ExpressionFunction.FunctionCall(functionName, argumentCount); var functionMapping = new FunctionMapping(mappedFunctionName); var function = new FunctionDefinition(functionCall, functionMapping, adapterVersion); functionMapping.FunctionMapper = mapper(function); return(function); }
private string FormatFunction(ExpressionContext context) { var adapterVersion = AdapterVersion.Default; if (FunctionToOperatorMapping.TryGetOperatorMapping(functionCaller, Function, adapterVersion, out var operatorMapping)) { return(FormatMappedOperator(context, operatorMapping)); } if (FunctionMapping.TryGetFunctionMapping(Function.FunctionName, Function.Arguments.Count(), adapterVersion, out var functionMapping)) { return(FormatMappedFunction(context, functionMapping)); } if (string.Equals(Function.FunctionName, ODataLiteral.Any, StringComparison.OrdinalIgnoreCase) || string.Equals(Function.FunctionName, ODataLiteral.All, StringComparison.OrdinalIgnoreCase)) { return(FormatAnyAllFunction(context)); } if (string.Equals(Function.FunctionName, ODataLiteral.IsOf, StringComparison.OrdinalIgnoreCase) || string.Equals(Function.FunctionName, ODataLiteral.Cast, StringComparison.OrdinalIgnoreCase)) { return(FormatIsOfCastFunction(context)); } if (string.Equals(Function.FunctionName, "get_Item", StringComparison.Ordinal) && Function.Arguments.Count == 1) { return(FormatArrayIndexFunction(context)); } if (string.Equals(Function.FunctionName, "HasFlag", StringComparison.Ordinal) && Function.Arguments.Count == 1) { return(FormatEnumHasFlagFunction(context)); } if (string.Equals(Function.FunctionName, "ToString", StringComparison.Ordinal) && Function.Arguments.Count == 0) { return(FormatToStringFunction(context)); } if (Function.Arguments.Count == 1) { var val = Function.Arguments.First(); if (val.Value != null) { var formattedVal = FromValue( string.Equals(Function.FunctionName, "ToBoolean", StringComparison.Ordinal) ? Convert.ToBoolean(val.Value) : string.Equals(Function.FunctionName, "ToByte", StringComparison.Ordinal) ? Convert.ToByte(val.Value) : string.Equals(Function.FunctionName, "ToChar", StringComparison.Ordinal) ? Convert.ToChar(val.Value) : string.Equals(Function.FunctionName, "ToDateTime", StringComparison.Ordinal) ? Convert.ToDateTime(val.Value) : string.Equals(Function.FunctionName, "ToDecimal", StringComparison.Ordinal) ? Convert.ToDecimal(val.Value) : string.Equals(Function.FunctionName, "ToDouble", StringComparison.Ordinal) ? Convert.ToDouble(val.Value) : string.Equals(Function.FunctionName, "ToInt16", StringComparison.Ordinal) ? Convert.ToInt16(val.Value) : string.Equals(Function.FunctionName, "ToInt32", StringComparison.Ordinal) ? Convert.ToInt32(val.Value) : string.Equals(Function.FunctionName, "ToInt64", StringComparison.Ordinal) ? Convert.ToInt64(val.Value) : string.Equals(Function.FunctionName, "ToSByte", StringComparison.Ordinal) ? Convert.ToSByte(val.Value) : string.Equals(Function.FunctionName, "ToSingle", StringComparison.Ordinal) ? Convert.ToSingle(val.Value) : string.Equals(Function.FunctionName, "ToString", StringComparison.Ordinal) ? Convert.ToString(val.Value) : string.Equals(Function.FunctionName, "ToUInt16", StringComparison.Ordinal) ? Convert.ToUInt16(val.Value) : string.Equals(Function.FunctionName, "ToUInt32", StringComparison.Ordinal) ? Convert.ToUInt32(val.Value) : string.Equals(Function.FunctionName, "ToUInt64", StringComparison.Ordinal) ? (object)Convert.ToUInt64(val.Value) : null); if (formattedVal.Value != null) { return(FormatExpression(formattedVal, context)); } } } throw new NotSupportedException($"The function {Function.FunctionName} is not supported or called with wrong number of arguments"); }
public static bool TryGetFunctionMapping(string functionName, int argumentCount, AdapterVersion adapterVersion, out FunctionMapping functionMapping) { functionMapping = null; var function = DefinedFunctions.SingleOrDefault(x => x.FunctionCall.Equals(new ExpressionFunction.FunctionCall(functionName, argumentCount)) && (x.AdapterVersion & adapterVersion) == adapterVersion); if (function != null) { functionMapping = function.FunctionMapping; } return(function != null); }
public FunctionDefinition(ExpressionFunction.FunctionCall functionCall, FunctionMapping functionMapping, AdapterVersion adapterVersion = AdapterVersion.Any) { FunctionCall = functionCall; FunctionMapping = functionMapping; AdapterVersion = adapterVersion; }