private static Func <string, string[], string> GetCompilerForCtor(
            IMemberCompilerProvider <string> provider, Type source)
        {
            if (source.IsGenericTypeDefinition)
            {
                source = source.MakeGenericType(typeof(object));
            }

            var ci     = source.GetConstructors().First();
            var result = provider.GetCompiler(ci);

            Assert.IsNotNull(result);
            return(result);
        }
        private static Func <string, string[], string> GetCompilerForField(
            IMemberCompilerProvider <string> provider, Type source, string fieldName)
        {
            if (source.IsGenericTypeDefinition)
            {
                source = source.MakeGenericType(typeof(object));
            }

            var fi = source.GetField(fieldName);

            Assert.IsNotNull(fi);
            var result = provider.GetCompiler(fi);

            Assert.IsNotNull(result);
            return(result);
        }
        private static Func <string, string[], string> GetCompilerForMethod(
            IMemberCompilerProvider <string> provider, Type source, string methodName)
        {
            if (source.IsGenericTypeDefinition)
            {
                source = source.MakeGenericType(typeof(object));
            }

            var mi = source.GetMethod(methodName);

            Assert.IsNotNull(mi);
            if (mi.IsGenericMethodDefinition)
            {
                mi = mi.MakeGenericMethod(typeof(object));
            }
            var result = provider.GetCompiler(mi);

            Assert.IsNotNull(result);
            return(result);
        }
        // Constructors

        public ExpressionProcessor(
            LambdaExpression lambda, HandlerAccessor handlers, SqlCompiler compiler, params IReadOnlyList <SqlExpression>[] sourceColumns)
        {
            ArgumentValidator.EnsureArgumentNotNull(lambda, "lambda");
            ArgumentValidator.EnsureArgumentNotNull(handlers, "handlers");
            ArgumentValidator.EnsureArgumentNotNull(sourceColumns, "sourceColumns");

            this.compiler      = compiler; // This might be null, check before use!
            this.lambda        = lambda;
            this.sourceColumns = sourceColumns;

            providerInfo = handlers.ProviderInfo;
            driver       = handlers.StorageDriver;

            fixBooleanExpressions      = !providerInfo.Supports(ProviderFeatures.FullFeaturedBooleanExpressions);
            emptyStringIsNull          = providerInfo.Supports(ProviderFeatures.TreatEmptyStringAsNull);
            dateTimeEmulation          = providerInfo.Supports(ProviderFeatures.DateTimeEmulation);
            dateTimeOffsetEmulation    = providerInfo.Supports(ProviderFeatures.DateTimeOffsetEmulation);
            memberCompilerProvider     = handlers.DomainHandler.GetMemberCompilerProvider <SqlExpression>();
            specialByteArrayComparison = providerInfo.ProviderName.Equals(WellKnown.Provider.Oracle);

            bindings           = new HashSet <QueryParameterBinding>();
            activeParameters   = new List <ParameterExpression>();
            evaluator          = new ExpressionEvaluator(lambda);
            parameterExtractor = new ParameterExtractor(evaluator);

            if (fixBooleanExpressions)
            {
                booleanExpressionConverter = new BooleanExpressionConverter(driver);
            }
            if (lambda.Parameters.Count != sourceColumns.Length)
            {
                throw Exceptions.InternalError(Strings.ExParametersCountIsNotSameAsSourceColumnListsCount, OrmLog.Instance);
            }
            if (sourceColumns.Any(list => list.Any(c => c.IsNullReference())))
            {
                throw Exceptions.InternalError(Strings.ExSourceColumnListContainsNullValues, OrmLog.Instance);
            }
            sourceMapping = new Dictionary <ParameterExpression, IReadOnlyList <SqlExpression> >();
        }