protected override Expression VisitMember(MemberExpression node)
        {
            Expression result = null;

            if (node.Expression != null && node.Expression.Type == typeof(TFrom))
            {
                Expression expression = this.Visit(node.Expression);
                if (expression.Type != typeof(TTo))
                {
                    throw new Exception("An error occurred");
                }
                LambdaExpression lambdaExpression;
                if (this.Mappings.TryGetValue(node.Member, out lambdaExpression))
                {
                    Expression param = lambdaExpression.Parameters.Single();
                    result = new FlexVisitor(
                        (expr) => expr == param,
                        (expr) => expression
                        ).Visit(lambdaExpression.Body);
                }
                else
                {
                    result = Expression.Property(expression, node.Member.Name);
                }
            }
            else
            {
                result = base.VisitMember(node);
            }
            return(result);
        }
Exemple #2
0
        public TResult Execute <TResult>(System.Linq.Expressions.Expression expression)
        {
            if (this.Transform == null)
            {
                throw new InvalidOperationException("Must specify a transform before performing a query against the TransformQueryProvider");
            }

            if (!this.Visitor.ConstantMappings.ContainsKey(this.ConstantExpression))
            {
                this.Visitor.ConstantMappings.Add(this.ConstantExpression, this.InnerQueryable.Expression);
            }

            TResult  result      = default(TResult);
            TypeInfo qType       = typeof(IQueryable).GetTypeInfo();
            Type     gqType      = typeof(IQueryable <>);
            TypeInfo gqTypeInfo  = gqType.GetTypeInfo();
            Type     resType     = typeof(TResult);
            TypeInfo resTypeInfo = resType.GetTypeInfo();

            // Check if the type being requested can accept an IQueryable<T>, in which case we should not evaluate the expression
            // but instead return a new query.  First check is to ensure the TResult type is an interface, otherwise the rest definitely
            // won't work, so returning null to short-circuit the logic.  Seems like the best way to do it for performance and compactness,
            // so lots of reflection operations don't needlessly occur.
            var query = !resTypeInfo.IsInterface
                ? null
                : (new TypeInfo[] { resTypeInfo })
                        .Union(resTypeInfo.GetInterfaces().Select(i => i.GetTypeInfo()))
                        .Where(i => i.IsGenericType &&
                               qType.IsAssignableFrom(i) &&
                               i.GetGenericTypeDefinition() == gqType)
                        .SingleOrDefault();

            if (query != null)
            {
                result = DynamicallyCreateQuery <TResult>(query.GetGenericArguments()[0], expression);
                //result = (TResult)this
                //    .CallMethod(
                //        new Type[] {
                //            query.GetGenericArguments()[0]
                //        },
                //        "CreateQuery",
                //        expression);
            }
            else if (resType == typeof(IEnumerable <TTo>))
            {
                expression = this.Visitor.Visit(expression);
                FlexVisitor vis = new FlexVisitor((exp) => exp == this.ConstantExpression, (exp) => this.InnerQueryable.Expression);
                expression = vis.Visit(expression);
                var temp = InnerQueryable.Provider.CreateQuery <TFrom>(expression).ToArray();
                if (this.Transform != null)
                {
                    result = (TResult)((object)temp.Select(o => Transform(o)));
                }
            }
            else if (resType == typeof(TTo))
            {
                expression = this.Visitor.Visit(expression);
                FlexVisitor vis = new FlexVisitor((exp) => exp == this.ConstantExpression, (exp) => this.InnerQueryable.Expression);
                expression = vis.Visit(expression);
                var temp = InnerQueryable.Provider.Execute <TFrom>(expression);
                if (this.Transform != null)
                {
                    result = (TResult)((object)Transform(temp));
                }
            }
            else
            {
                expression = this.Visitor.Visit(expression);
                FlexVisitor vis = new FlexVisitor((exp) => exp == this.ConstantExpression, (exp) => this.InnerQueryable.Expression);
                expression = vis.Visit(expression);
                result     = InnerQueryable.Provider.Execute <TResult>(expression);
            }

            return(result);
        }