Exemple #1
0
        private ConstructedValueExpression MapTupleParameters(MapTypeContext context, MethodInfo factoryMethod, Type[] typeParams)
        {
            var expressions = new List <Expression>();
            var variables   = new List <ParameterExpression>();
            var args        = new Expression[typeParams.Length];

            // We need to assign a value to every parameter. Loop over each parameter and map values where
            // available. When we run out of columns or have a column we cannot map, fill in a default value.
            // Where a value type may consume many columns (a custom object type, for example) it will
            // greedily consume as much as possible before moving to the next parameter.
            for (var i = 0; i < typeParams.Length; i++)
            {
                if (!context.HasColumns())
                {
                    args[i] = typeParams[i].GetDefaultValueExpression();
                    continue;
                }

                var elementState = context.ChangeTargetType(typeParams[i]);
                var expr         = _values.Compile(elementState);
                if (expr.IsNothing)
                {
                    args[i] = typeParams[i].GetDefaultValueExpression();
                    continue;
                }

                expressions.AddRange(expr.Expressions);
                variables.AddRange(expr.Variables);
                args[i] = expr.FinalValue;
            }
            return(new ConstructedValueExpression(expressions, Expression.Call(null, factoryMethod, args), variables));
        }
        public ConstructedValueExpression Compile(MapTypeContext context)
        {
            if (!IsSupportedType(context.TargetType))
            {
                return(ConstructedValueExpression.Nothing);
            }

            // Get the concrete type to construct, the element type to populate, and the Add
            // method to call for each value
            var(collectionType, elementType, constructor, addMethod) = GetConcreteTypeInfo(context);
            Debug.Assert(collectionType != null);
            Debug.Assert(context.TargetType.IsAssignableFrom(collectionType));
            Debug.Assert(elementType != null);
            Debug.Assert(addMethod != null);
            Debug.Assert(constructor != null);

            var originalTargetType = context.TargetType;

            context = context.ChangeTargetType(collectionType);

            // Get a list of expressions to create the collection instance and populate it with
            // values
            var collectionVar = CollectionExpressionFactory.GetMaybeInstantiateCollectionExpression(context, constructor);
            var addStmts      = CollectionExpressionFactory.GetCollectionPopulateStatements(_scalars, _nonScalars, context, elementType, collectionVar.FinalValue, addMethod);

            return(new ConstructedValueExpression(
                       collectionVar.Expressions.Concat(addStmts.Expressions),
                       Expression.Convert(collectionVar.FinalValue, originalTargetType),
                       collectionVar.Variables.Concat(addStmts.Variables)
                       ));
        }
Exemple #3
0
        public ConstructedValueExpression Compile(MapTypeContext context)
        {
            if (context.TargetType != typeof(object))
            {
                return(ConstructedValueExpression.Nothing);
            }

            // At the top-level (name==null) we convert to dictionary to preserve column name information
            if (context.Name == null)
            {
                // Dictionary mapping logic will group by key name and recurse. When we get back to the
                // ObjectCompiler, we will have a smaller set of columns and we will have a non-null name
                var dictState = context.ChangeTargetType(typeof(Dictionary <string, object>));
                var dictExpr  = _dictionaries.Compile(dictState);
                return(new ConstructedValueExpression(dictExpr.Expressions, Expression.Convert(dictExpr.FinalValue, typeof(object)), dictExpr.Variables));
            }

            var columns    = context.GetColumns().ToList();
            var numColumns = columns.Count;

            // If we have no columns, just return null
            if (numColumns == 0)
            {
                return(new ConstructedValueExpression(
                           Expression.Convert(
                               Expression.Constant(null),
                               typeof(object)
                               )
                           ));
            }

            // If we have exactly one column, map the value as a scalar and return a single result
            if (numColumns == 1)
            {
                var firstColumn = columns[0];
                var objectState = context.GetSubstateForColumn(firstColumn, typeof(object), null);
                var asScalar    = _scalars.Compile(objectState);
                return(new ConstructedValueExpression(asScalar.Expressions, Expression.Convert(asScalar.FinalValue, typeof(object)), asScalar.Variables));
            }

            // If we have more than one column, map to object[]
            var arrayState = context.ChangeTargetType(typeof(object[]));
            var exprs      = _arrays.Compile(arrayState);

            return(new ConstructedValueExpression(exprs.Expressions, Expression.Convert(exprs.FinalValue, typeof(object)), exprs.Variables));
        }
Exemple #4
0
        public static ConstructedValueExpression GetCollectionPopulateStatements(ICompiler scalars, ICompiler nonScalars, MapTypeContext context, Type elementType, Expression listVar, MethodInfo addMethod)
        {
            if (!context.HasColumns())
            {
                return(new ConstructedValueExpression(null));
            }

            var expressions = new List <Expression>();
            var variables   = new List <ParameterExpression>();

            // For scalar types (object is treated like a scalar here), map each column to an entry in the
            // array, consuming all remaining columns.
            if (elementType.IsSupportedPrimitiveType() || elementType == typeof(object))
            {
                var columns = context.GetColumns();
                foreach (var column in columns)
                {
                    var columnState = context.GetSubstateForColumn(column, elementType, null);
                    var result      = scalars.Compile(columnState);
                    expressions.AddRange(result.Expressions);
                    expressions.Add(
                        Expression.Call(
                            listVar,
                            addMethod,
                            result.FinalValue
                            )
                        );
                    variables.AddRange(result.Variables);
                }

                return(new ConstructedValueExpression(expressions, null, variables));
            }

            // For all non-scalar types
            // loop so long as we have columns and consume columns every iteration.
            var elementState    = context.ChangeTargetType(elementType);
            var numberOfColumns = context.NumberOfColumns();

            while (numberOfColumns > 0)
            {
                var result             = nonScalars.Compile(elementState);
                var newNumberOfColumns = context.NumberOfColumns();

                // We haven't consumed any new columns, so we're done.
                if (newNumberOfColumns == numberOfColumns)
                {
                    break;
                }
                expressions.AddRange(result.Expressions);
                expressions.Add(
                    Expression.Call(listVar, addMethod, result.FinalValue)
                    );
                variables.AddRange(result.Variables);
                numberOfColumns = newNumberOfColumns;
            }
            return(new ConstructedValueExpression(expressions, null, variables));
        }
Exemple #5
0
        private ConstructedValueExpression CompileArrayOfCustomObject(MapTypeContext context, Type elementType, ConstructorInfo constructor)
        {
            var expressions = new List <Expression>();
            var variables   = new List <ParameterExpression>();

            // We don't loop here because we need to know how many items we have in the array and we
            // can't calculate that because the custom object might consume any number of columns. We don't
            // know until after each iteration has returned how many columns are left. We could map to
            // a List and then .ToArray() to get the array, but that seems wasteful.

            var arrayVar = context.CreateVariable(context.TargetType, "array");

            variables.Add(arrayVar);
            var elementState = context.ChangeTargetType(elementType);
            var result       = _customObjects.Compile(elementState);

            expressions.AddRange(result.Expressions);

            // Create a new array with a length of 1
            expressions.Add(
                Expression.Assign(
                    arrayVar,
                    Expression.New(
                        constructor,
                        Expression.Constant(1)
                        )
                    )
                );

            // Set the value to the first slot in the array
            expressions.Add(
                Expression.Assign(
                    Expression.ArrayAccess(
                        arrayVar,
                        Expression.Constant(0)
                        ),
                    result.FinalValue
                    )
                );
            variables.AddRange(result.Variables);
            return(new ConstructedValueExpression(expressions, arrayVar, variables));
        }
        public ConstructedValueExpression Compile(MapTypeContext context)
        {
            if (!IsSupportedType(context.TargetType))
            {
                return(ConstructedValueExpression.Nothing);
            }

            var genericArguments = context.TargetType.GetGenericArguments();

            Debug.Assert(genericArguments.Length == 2);

            var keyType = typeof(string);

            Debug.Assert(genericArguments[0] == typeof(string));

            var elementType = context.TargetType.GetGenericArguments()[1];

            Debug.Assert(elementType != null);

            var typeInfo = GetConcreteTypeInfo(context, keyType, elementType);
            var dictType = typeInfo.ConcreteType;

            Debug.Assert(dictType != null);

            var constructor = typeInfo.Constructor;

            Debug.Assert(constructor != null);

            var addMethod = typeInfo.AddMethod;

            Debug.Assert(addMethod != null);

            var concreteState = context.ChangeTargetType(dictType);
            var dictVar       = DictionaryExpressionFactory.GetMaybeInstantiateDictionaryExpression(concreteState, constructor);
            var addStmts      = DictionaryExpressionFactory.AddDictionaryPopulateStatements(_valueCompiler, concreteState, elementType, dictVar.FinalValue, addMethod);

            return(new ConstructedValueExpression(
                       dictVar.Expressions.Concat(addStmts.Expressions),
                       Expression.Convert(dictVar.FinalValue, context.TargetType),
                       dictVar.Variables.Concat(addStmts.Variables)
                       ));
        }