示例#1
0
        /// <summary>
        /// Visit :: x => x.Customer.Name.`ToUpper()`
        /// </summary>
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            // get method declaring type - if is from any kind of list, read as Enumerable
            var isList = Reflection.IsList(node.Method.DeclaringType);

            var declaringType = isList ? typeof(Enumerable) : node.Method.DeclaringType;

            // if special method for index access, eval index value (do not use parameters)
            if (this.IsMethodIndexEval(node, out var obj, out var idx))
            {
                this.Visit(obj);

                var index = this.Evaluate(idx, typeof(string), typeof(int));

                if (index is string)
                {
                    _builder.Append(".");
                    _builder.Append($"['{index}']");
                }
                else
                {
                    _builder.Append($"[{index}]");
                }

                return(node);
            }

            // if not found in resolver, try run method
            if (!_resolver.TryGetValue(declaringType, out var type))
            {
                // if method are called by parameter expression and it's not exists, throw error
                var isParam = ParameterExpressionVisitor.Test(node);

                if (isParam)
                {
                    throw new NotSupportedException($"Method {node.Method.Name} not available to convert to BsonExpression ({node.ToString()}).");
                }

                // otherwise, try compile and execute
                var value = this.Evaluate(node);

                base.Visit(Expression.Constant(value));

                return(node);
            }

            // otherwise I have resolver for this method
            var pattern = type.ResolveMethod(node.Method);

            if (pattern == null)
            {
                throw new NotSupportedException($"Method {Reflection.MethodName(node.Method)} in {node.Method.DeclaringType.Name} are not supported when convert to BsonExpression ({node.ToString()}).");
            }

            // run pattern using object as # and args as @n
            this.ResolvePattern(pattern, node.Object, node.Arguments);

            return(node);
        }
        public static bool Test(Expression node)
        {
            var instance = new ParameterExpressionVisitor();

            instance.Visit(node);

            return(instance.IsParameter);
        }
示例#3
0
        /// <summary>
        /// Visit :: x => x.`Customer.Name`
        /// </summary>
        protected override Expression VisitMember(MemberExpression node)
        {
            // test if member access is based on parameter expression or constant/external variable
            var isParam = ParameterExpressionVisitor.Test(node);

            var member = node.Member;

            // special types contains method access: string.Length, DateTime.Day, ...
            if (this.TryGetResolver(member.DeclaringType, out var type))
            {
                var pattern = type.ResolveMember(member);

                if (pattern == null)
                {
                    throw new NotSupportedException($"Member {member.Name} are not support in {member.DeclaringType.Name} when convert to BsonExpression ({node.ToString()}).");
                }

                this.ResolvePattern(pattern, node.Expression, new Expression[0]);
            }
            else
            {
                // for static member, Expression == null
                if (node.Expression != null)
                {
                    _nodes.Push(node);

                    base.Visit(node.Expression);

                    if (isParam)
                    {
                        var name = this.ResolveMember(member);

                        _builder.Append(name);
                    }
                }
                // static member is not parameter expression - compile and execute as constant
                else
                {
                    var value = this.Evaluate(node);

                    base.Visit(Expression.Constant(value));
                }
            }

            if (_nodes.Count > 0)
            {
                _nodes.Pop();
            }


            return(node);
        }