Esempio n. 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)));
            }
            else
            {
                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 FormatFunction(ExpressionContext context)
        {
            FunctionMapping mapping;
            var             adapterVersion = context.Session == null ? AdapterVersion.Default : context.Session.Adapter.AdapterVersion;

            if (FunctionMapping.TryGetFunctionMapping(this.Function.FunctionName, this.Function.Arguments.Count(), adapterVersion, out mapping))
            {
                var mappedFunction     = mapping.FunctionMapper(this.Function.FunctionName, _functionCaller.Format(context), this.Function.Arguments).Function;
                var formattedArguments = string.Join(",", (IEnumerable <object>)mappedFunction.Arguments.Select(x => FormatExpression(x, context)));

                return(string.Format("{0}({1})",
                                     mappedFunction.FunctionName, formattedArguments));
            }
            else if (string.Equals(this.Function.FunctionName, ODataLiteral.Any, StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(this.Function.FunctionName, ODataLiteral.All, StringComparison.OrdinalIgnoreCase))
            {
                var formattedArguments = string.Format("x{0}:x{0}/{1}",
                                                       ArgumentCounter >= 0 ? (1 + (ArgumentCounter++) % 9).ToString() : string.Empty,
                                                       FormatExpression(this.Function.Arguments.First(), new ExpressionContext(context.Session,
                                                                                                                               new EntityCollection(_functionCaller.Reference, context.EntityCollection))));

                return(string.Format("{0}/{1}({2})",
                                     _functionCaller.Format(context), this.Function.FunctionName.ToLower(), formattedArguments));
            }
            else
            {
                throw new NotSupportedException(string.Format("The function {0} is not supported or called with wrong number of arguments", this.Function.FunctionName));
            }
        }
Esempio n. 3
0
            public override DynamicMetaObject BindInvokeMember(
                InvokeMemberBinder binder, DynamicMetaObject[] args)
            {
                if (FunctionMapping.ContainsFunction(binder.Name, args.Count()))
                {
                    var expression = Expression.New(CtorWithExpressionAndExpressionFunction,
                                                    new[]
                    {
                        Expression.Constant(this.Value),
                        Expression.Constant(new ExpressionFunction(binder.Name, args.Select(x => x.Value)))
                    });

                    return(new DynamicMetaObject(
                               expression,
                               BindingRestrictions.GetTypeRestriction(Expression, LimitType)));
                }
                else if (string.Equals(binder.Name, ODataLiteral.Any, StringComparison.OrdinalIgnoreCase) ||
                         string.Equals(binder.Name, ODataLiteral.All, StringComparison.OrdinalIgnoreCase))
                {
                    var expression = Expression.New(CtorWithExpressionAndExpressionFunction,
                                                    new[]
                    {
                        Expression.Constant(this.Value),
                        Expression.Constant(new ExpressionFunction(binder.Name, args.Select(x => x.Value)))
                    });

                    return(new DynamicMetaObject(
                               expression,
                               BindingRestrictions.GetTypeRestriction(Expression, LimitType)));
                }
                else
                {
                    return(base.BindInvokeMember(binder, args));
                }
            }
Esempio n. 4
0
        private bool IsFunction(string objectName, ExpressionContext context)
        {
            FunctionMapping mapping;
            var             adapterVersion = context.Session == null ? AdapterVersion.Default : context.Session.Adapter.AdapterVersion;

            return(FunctionMapping.TryGetFunctionMapping(objectName, 0, adapterVersion, out mapping));
        }
Esempio n. 5
0
        private string FormatFunction(ExpressionContext context)
        {
            FunctionMapping mapping;
            var             adapterVersion = context.Session == null ? AdapterVersion.Default : context.Session.Adapter.AdapterVersion;

            if (FunctionMapping.TryGetFunctionMapping(this.Function.FunctionName, this.Function.Arguments.Count(), adapterVersion, out mapping))
            {
                return(FormatMappedFunction(context, mapping));
            }
            else if (string.Equals(this.Function.FunctionName, ODataLiteral.Any, StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(this.Function.FunctionName, ODataLiteral.All, StringComparison.OrdinalIgnoreCase))
            {
                return(FormatAnyAllFunction(context));
            }
            else if (string.Equals(this.Function.FunctionName, ODataLiteral.IsOf, StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(this.Function.FunctionName, ODataLiteral.Cast, StringComparison.OrdinalIgnoreCase))
            {
                return(FormatIsOfCastFunction(context));
            }
            else if (string.Equals(this.Function.FunctionName, "get_Item", StringComparison.Ordinal) &&
                     this.Function.Arguments.Count == 1)
            {
                return(FormatArrayIndexFunction(context));
            }
            else if (string.Equals(this.Function.FunctionName, "ToString", StringComparison.Ordinal) &&
                     this.Function.Arguments.Count == 0)
            {
                return(_functionCaller.Reference);
            }
            else if (_functionCaller.IsNull && this.Function.Arguments.Count == 1)
            {
                var val = this.Function.Arguments.First();
                if (val.Value != null)
                {
                    var formattedVal = ODataExpression.FromValue(
                        string.Equals(this.Function.FunctionName, "ToBoolean", StringComparison.Ordinal) ? Convert.ToBoolean(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToByte", StringComparison.Ordinal) ? Convert.ToByte(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToChar", StringComparison.Ordinal) ? Convert.ToChar(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToDateTime", StringComparison.Ordinal) ? Convert.ToDateTime(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToDecimal", StringComparison.Ordinal) ? Convert.ToDecimal(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToDouble", StringComparison.Ordinal) ? Convert.ToDouble(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToInt16", StringComparison.Ordinal) ? Convert.ToInt16(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToInt32", StringComparison.Ordinal) ? Convert.ToInt32(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToInt64", StringComparison.Ordinal) ? Convert.ToInt64(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToSByte", StringComparison.Ordinal) ? Convert.ToSByte(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToSingle", StringComparison.Ordinal) ? Convert.ToSingle(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToString", StringComparison.Ordinal) ? Convert.ToString(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToUInt16", StringComparison.Ordinal) ? Convert.ToUInt16(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToUInt32", StringComparison.Ordinal) ? Convert.ToUInt32(val.Value) :
                        string.Equals(this.Function.FunctionName, "ToUInt64", StringComparison.Ordinal) ? (object)Convert.ToUInt64(val.Value)
                        : null);
                    if (formattedVal.Value != null)
                    {
                        return(FormatExpression(formattedVal, context));
                    }
                }
            }

            throw new NotSupportedException(string.Format("The function {0} is not supported or called with wrong number of arguments", this.Function.FunctionName));
        }
        private string FormatFunction(ExpressionContext context)
        {
            FunctionMapping mapping;
            var             adapterVersion = context.Session == null ? AdapterVersion.Default : context.Session.Adapter.AdapterVersion;

            if (FunctionMapping.TryGetFunctionMapping(this.Function.FunctionName, this.Function.Arguments.Count(), adapterVersion, out mapping))
            {
                return(FormatMappedFunction(context, mapping));
            }
            else if (string.Equals(this.Function.FunctionName, ODataLiteral.Any, StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(this.Function.FunctionName, ODataLiteral.All, StringComparison.OrdinalIgnoreCase))
            {
                return(FormatAnyAllFunction(context));
            }
            else if (string.Equals(this.Function.FunctionName, ODataLiteral.IsOf, StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(this.Function.FunctionName, ODataLiteral.Cast, StringComparison.OrdinalIgnoreCase))
            {
                return(FormatIsOfCastFunction(context));
            }
            else if (string.Equals(this.Function.FunctionName, "get_Item", StringComparison.Ordinal) &&
                     this.Function.Arguments.Count == 1)
            {
                return(FormatArrayIndexFunction(context));
            }
            else if (string.Equals(this.Function.FunctionName, "ToString", StringComparison.Ordinal) &&
                     this.Function.Arguments.Count == 0)
            {
                return(_functionCaller.Reference);
            }
            else
            {
                throw new NotSupportedException(string.Format("The function {0} is not supported or called with wrong number of arguments", this.Function.FunctionName));
            }
        }
Esempio n. 7
0
            public override DynamicMetaObject BindInvokeMember(
                InvokeMemberBinder binder, DynamicMetaObject[] args)
            {
                var expressionFunctionConstructor = typeof(ExpressionFunction).GetConstructor(new[] { typeof(string), typeof(IEnumerable <object>) });

                if (FunctionMapping.ContainsFunction(binder.Name, args.Length))
                {
                    var expression = Expression.New(CtorWithExpressionAndExpressionFunction,
                                                    Expression.Convert(Expression, LimitType),
                                                    Expression.New(expressionFunctionConstructor,
                                                                   Expression.Constant(binder.Name),
                                                                   Expression.NewArrayInit(typeof(object), args.Select(x => Expression.Convert(x.Expression, typeof(object))))));

                    return(new DynamicMetaObject(
                               expression,
                               BindingRestrictions.GetTypeRestriction(Expression, LimitType)));
                }
                if (string.Equals(binder.Name, ODataLiteral.Any, StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(binder.Name, ODataLiteral.All, StringComparison.OrdinalIgnoreCase))
                {
                    var expression = Expression.New(CtorWithExpressionAndExpressionFunction,
                                                    Expression.Convert(Expression, LimitType),
                                                    Expression.New(expressionFunctionConstructor,
                                                                   Expression.Constant(binder.Name),
                                                                   Expression.NewArrayInit(typeof(object), args.Select(x => Expression.Convert(x.Expression, typeof(object))))));

                    return(new DynamicMetaObject(
                               expression,
                               BindingRestrictions.GetTypeRestriction(Expression, LimitType)));
                }
                if (string.Equals(binder.Name, ODataLiteral.IsOf, StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(binder.Name, ODataLiteral.Is, StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(binder.Name, ODataLiteral.Cast, StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(binder.Name, ODataLiteral.As, StringComparison.OrdinalIgnoreCase))
                {
                    var functionName = string.Equals(binder.Name, ODataLiteral.Is, StringComparison.OrdinalIgnoreCase)
                        ? ODataLiteral.IsOf
                        : string.Equals(binder.Name, ODataLiteral.As, StringComparison.OrdinalIgnoreCase)
                            ? ODataLiteral.Cast
                            : binder.Name;

                    var isNullProperty = typeof(DynamicODataExpression).GetProperty(nameof(IsNull));
                    var expressionFunctionArguments = Expression.Condition(Expression.MakeMemberAccess(Expression.Convert(Expression, LimitType), isNullProperty),
                                                                           Expression.Convert(Expression, typeof(object)),
                                                                           Expression.Convert(args.First().Expression, typeof(object)));

                    var expression = Expression.New(CtorWithExpressionAndExpressionFunction,
                                                    Expression.Convert(Expression, LimitType),
                                                    Expression.New(expressionFunctionConstructor,
                                                                   Expression.Constant(functionName),
                                                                   Expression.NewArrayInit(typeof(object), expressionFunctionArguments)));

                    return(new DynamicMetaObject(
                               expression,
                               BindingRestrictions.GetTypeRestriction(Expression, LimitType)));
                }

                return(base.BindInvokeMember(binder, args));
            }
        private string FormatMappedFunction(ExpressionContext context, FunctionMapping mapping)
        {
            var mappedFunction = mapping.FunctionMapper(
                this.Function.FunctionName, _functionCaller, this.Function.Arguments).Function;
            var formattedArguments = string.Join(",",
                                                 (IEnumerable <object>)mappedFunction.Arguments.Select(x => FormatExpression(x, context)));

            return($"{mappedFunction.FunctionName}({formattedArguments})");
        }
        private IEnumerable <string> BuildReferencePath(List <string> segmentNames, EntityCollection entityCollection, List <string> elementNames, ExpressionContext context)
        {
            if (!elementNames.Any())
            {
                return(segmentNames);
            }

            var objectName = elementNames.First();

            if (entityCollection != null)
            {
                if (context.Session.Metadata.HasStructuralProperty(entityCollection.Name, objectName))
                {
                    var propertyName = context.Session.Metadata.GetStructuralPropertyExactName(
                        entityCollection.Name, objectName);
                    segmentNames.Add(propertyName);
                    return(BuildReferencePath(segmentNames, null, elementNames.Skip(1).ToList(), context));
                }
                else if (context.Session.Metadata.HasNavigationProperty(entityCollection.Name, objectName))
                {
                    var propertyName = context.Session.Metadata.GetNavigationPropertyExactName(
                        entityCollection.Name, objectName);
                    var linkName = context.Session.Metadata.GetNavigationPropertyPartnerTypeName(
                        entityCollection.Name, objectName);
                    var linkedEntityCollection = context.Session.Metadata.GetEntityCollection(linkName);
                    segmentNames.Add(propertyName);
                    return(BuildReferencePath(segmentNames, linkedEntityCollection, elementNames.Skip(1).ToList(), context));
                }
                else if (IsFunction(objectName, context))
                {
                    var formattedFunction = FormatAsFunction(objectName, context);
                    segmentNames.Add(formattedFunction);
                    return(BuildReferencePath(segmentNames, null, elementNames.Skip(1).ToList(), context));
                }
                else if (context.Session.Metadata.IsOpenType(entityCollection.Name))
                {
                    segmentNames.Add(objectName);
                    return(BuildReferencePath(segmentNames, null, elementNames.Skip(1).ToList(), context));
                }
                else
                {
                    throw new UnresolvableObjectException(objectName, $"Invalid referenced object [{objectName}]");
                }
            }
            else if (FunctionMapping.ContainsFunction(elementNames.First(), 0))
            {
                var formattedFunction = FormatAsFunction(objectName, context);
                segmentNames.Add(formattedFunction);
                return(BuildReferencePath(segmentNames, null, elementNames.Skip(1).ToList(), context));
            }
            else
            {
                segmentNames.AddRange(elementNames);
                return(BuildReferencePath(segmentNames, null, new List <string>(), context));
            }
        }
        private static FunctionDefinition CreateFunctionDefinition(string functionName, int argumentCount, string mappedFunctionName,
                                                                   Func <FunctionDefinition, Func <string, string, 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 FormatAsFunction(string objectName, ExpressionContext context)
        {
            var adapterVersion = context.Session?.Adapter.AdapterVersion ?? AdapterVersion.Default;

            if (FunctionMapping.TryGetFunctionMapping(objectName, 0, adapterVersion, out var mapping))
            {
                var mappedFunction = mapping.FunctionMapper(objectName, _functionCaller, null).Function;
                return($"{mappedFunction.FunctionName}({FormatCallerReference()})");
            }
            else
            {
                return(null);
            }
        }
Esempio n. 12
0
        private string FormatAsFunction(string objectName, ExpressionContext context)
        {
            FunctionMapping mapping;
            var             adapterVersion = context.Session == null ? AdapterVersion.Default : context.Session.Adapter.AdapterVersion;

            if (FunctionMapping.TryGetFunctionMapping(objectName, 0, adapterVersion, out mapping))
            {
                var mappedFunction = mapping.FunctionMapper(objectName, _functionCaller, null).Function;
                return(string.Format("{0}({1})", mappedFunction.FunctionName, FormatCallerReference()));
            }
            else
            {
                return(null);
            }
        }
        private static ODataExpression ParseMemberExpression(Expression expression, Stack <MemberInfo> memberChain = null)
        {
            var memberExpression = expression as MemberExpression;

            if (memberExpression.Expression == null)
            {
                return(new ODataExpression(EvaluateStaticMember(memberExpression)));
            }
            else
            {
                memberChain ??= new Stack <MemberInfo>();
                memberChain.Push(memberExpression.Member);
                switch (memberExpression.Expression.NodeType)
                {
                case ExpressionType.Parameter:
                    // NOTE: Can't support ITypeCache here as we might be dealing with dynamic types/expressions
                    var memberNames = string.Join(".", memberChain.Select(x => x.GetMappedName()));
                    return(FromReference(memberNames));

                case ExpressionType.Constant:
                    return(ParseConstantExpression(memberExpression.Expression, memberChain));

                case ExpressionType.MemberAccess:
                    // NOTE: Can't support ITypeCache here as we might be dealing with dynamic types/expressions
                    var memberName = memberExpression.Member.GetMappedName();
                    if (FunctionMapping.ContainsFunction(memberName, 0))
                    {
                        return(FromFunction(memberName, ParseMemberExpression(memberExpression.Expression), new List <object>()));
                    }
                    else
                    {
                        return(ParseMemberExpression(memberExpression.Expression as MemberExpression, memberChain));
                    }

                default:
                    throw Utils.NotSupportedExpression(expression);
                }
            }
        }
Esempio n. 14
0
            public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
            {
                ConstructorInfo ctor;

                Expression[] ctorArguments;
                if (FunctionMapping.ContainsFunction(binder.Name, 0))
                {
                    ctor          = CtorWithExpressionAndString;
                    ctorArguments = new[] { Expression.Constant(this.Value), Expression.Constant(binder.Name) };
                }
                else
                {
                    var reference = this.HasValue && !string.IsNullOrEmpty((this.Value as ODataExpression).Reference)
                        ? string.Join("/", (this.Value as ODataExpression).Reference, binder.Name)
                        : binder.Name;
                    ctor          = CtorWithString;
                    ctorArguments = new[] { Expression.Constant(reference) };
                }

                return(new DynamicMetaObject(
                           Expression.New(ctor, ctorArguments),
                           BindingRestrictions.GetTypeRestriction(Expression, LimitType)));
            }
Esempio n. 15
0
            public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
            {
                ConstructorInfo ctor;

                Expression[] ctorArguments;
                if (FunctionMapping.ContainsFunction(binder.Name, 0))
                {
                    ctor          = CtorWithExpressionAndString;
                    ctorArguments = new Expression[] { Expression.Convert(Expression, LimitType), Expression.Constant(binder.Name) };
                }
                else
                {
                    Expression <Func <bool, ODataExpression, string> > calculateReference = (hv, e) => hv && !string.IsNullOrEmpty(e.Reference)
                        ? string.Join("/", e.Reference, binder.Name)
                        : binder.Name;
                    var referenceExpression = Expression.Invoke(calculateReference, Expression.Constant(HasValue), Expression.Convert(Expression, LimitType));
                    ctor          = CtorWithString;
                    ctorArguments = new Expression[] { referenceExpression };
                }

                return(new DynamicMetaObject(
                           Expression.New(ctor, ctorArguments),
                           BindingRestrictions.GetTypeRestriction(Expression, LimitType)));
            }
        private bool IsFunction(string objectName, ExpressionContext context)
        {
            var adapterVersion = context.Session?.Adapter.AdapterVersion ?? AdapterVersion.Default;

            return(FunctionMapping.TryGetFunctionMapping(objectName, 0, adapterVersion, out _));
        }
 public FunctionDefinition(ExpressionFunction.FunctionCall functionCall, FunctionMapping functionMapping, AdapterVersion adapterVersion = AdapterVersion.Any)
 {
     FunctionCall = functionCall;
     FunctionMapping = functionMapping;
     AdapterVersion = adapterVersion;
 }
 private static FunctionDefinition CreateFunctionDefinition(string functionName, int argumentCount, string mappedFunctionName, 
     Func<FunctionDefinition, Func<string, string, 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;
 }
        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 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;
 }
        private string FormatMappedFunction(ExpressionContext context, FunctionMapping mapping)
        {
            var mappedFunction = mapping.FunctionMapper(
                this.Function.FunctionName, _functionCaller.Format(context), this.Function.Arguments).Function;
            var formattedArguments = string.Join(",",
                (IEnumerable<object>)mappedFunction.Arguments.Select(x => FormatExpression(x, context)));

            return string.Format("{0}({1})",
                mappedFunction.FunctionName,
                formattedArguments);
        }