private void RegisterMemberTemplateMapping(MemberExpression templateMember, Func <Term[], Term> termConstructor)
        {
            var member        = templateMember.Member;
            var declaringType = member.DeclaringType;
            var memberName    = member.Name;

            DefaultExpressionConverterFactory.ExpressionMappingDelegate <MemberExpression> del = delegate(
                MemberExpression queryExpression,
                DefaultExpressionConverterFactory.RecursiveMapDelegate recursiveMap,
                IDatumConverterFactory datumConverterFactory,
                IExpressionConverterFactory internalExpressionConverterFactory)
            {
                if (templateMember.Expression == null)
                {
                    // static member
                    return(termConstructor(new Term[0]));
                }
                else
                {
                    return(termConstructor(new Term[] { recursiveMap(queryExpression.Expression) }));
                }
            };

            RegisterMemberAccessMapping(declaringType, memberName, del);
        }
        private void RegisterUnaryTemplateMapping(UnaryExpression templateUnary, Func <Term, Term> termConstructor)
        {
            var expressionType = templateUnary.NodeType;
            var innerType      = templateUnary.Operand.Type;

            DefaultExpressionConverterFactory.ExpressionMappingDelegate <UnaryExpression> del = delegate(
                UnaryExpression queryExpression,
                DefaultExpressionConverterFactory.RecursiveMapDelegate recursiveMap,
                IDatumConverterFactory datumConverterFactory,
                IExpressionConverterFactory internalExpressionConverterFactory)
            {
                return(termConstructor(recursiveMap(queryExpression.Operand)));
            };

            RegisterUnaryExpressionMapping(innerType, expressionType, del);
        }
        private void RegisterNewTemplateMapping(NewExpression templateNew, Func <Term[], Term> termConstructor)
        {
            var templateConstructor = templateNew.Constructor;

            DefaultExpressionConverterFactory.ExpressionMappingDelegate <NewExpression> del = delegate(
                NewExpression queryExpression,
                DefaultExpressionConverterFactory.RecursiveMapDelegate recursiveMap,
                IDatumConverterFactory datumConverterFactory,
                IExpressionConverterFactory internalExpressionConverterFactory)
            {
                if (queryExpression.Arguments.Count != templateConstructor.GetParameters().Length)
                {
                    throw new InvalidOperationException("Unexpected mismatch between template method and query method");
                }
                var mappedArguments = queryExpression.Arguments.Select(expr => recursiveMap(expr));
                return(termConstructor(mappedArguments.ToArray()));
            };

            RegisterNewExpressionMapping(templateConstructor, del);
        }
        private void RegisterBinaryTemplateMapping(BinaryExpression templateBinary, Func <Term, Term, Term> termConstructor)
        {
            var leftType       = templateBinary.Left.Type;
            var expressionType = templateBinary.NodeType;
            var rightType      = templateBinary.Right.Type;

            DefaultExpressionConverterFactory.ExpressionMappingDelegate <BinaryExpression> del = delegate(
                BinaryExpression queryExpression,
                DefaultExpressionConverterFactory.RecursiveMapDelegate recursiveMap,
                IDatumConverterFactory datumConverterFactory,
                IExpressionConverterFactory internalExpressionConverterFactory)
            {
                return(termConstructor(recursiveMap(queryExpression.Left), recursiveMap(queryExpression.Right)));
            };

            RegisterBinaryExpressionMapping(leftType, rightType, expressionType, del);
        }
        private void RegisterMethodCallTemplateMapping(MethodCallExpression templateMethodCall, Func <Term[], Term> termConstructor)
        {
            var templateMethod = templateMethodCall.Method;

            DefaultExpressionConverterFactory.ExpressionMappingDelegate <MethodCallExpression> del = delegate(
                MethodCallExpression queryExpression,
                DefaultExpressionConverterFactory.RecursiveMapDelegate recursiveMap,
                IDatumConverterFactory datumConverterFactory,
                IExpressionConverterFactory internalExpressionConverterFactory)
            {
                if (queryExpression.Arguments.Count != templateMethodCall.Arguments.Count)
                {
                    throw new InvalidOperationException("Unexpected mismatch between template method and query method");
                }

                // If this is an instance method, we assume the first parameter is the object.  Technically we could
                // figure this out by inspecting templateMethodCall.Object, but this is a simple assumption for now.
                var mappedArguments = queryExpression.Arguments.Select(expr => recursiveMap(expr));
                if (templateMethodCall.Object != null)
                {
                    return(termConstructor(new Term[] { recursiveMap(queryExpression.Object) }.Concat(mappedArguments).ToArray()));
                }
                else
                {
                    return(termConstructor(mappedArguments.ToArray()));
                }
            };

            RegisterMethodCallMapping(templateMethod, del);
        }