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); } } }
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)); } }
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 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 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); } } }
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))); }
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))); }