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