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