Example #1
0
        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;
 }