public ConstructedValueExpression Compile(MapTypeContext context)
        {
            if (!context.TargetType.IsSupportedPrimitiveType() && context.TargetType != typeof(object))
            {
                return(ConstructedValueExpression.Nothing);
            }

            var column = context.SingleColumn();

            if (column == null)
            {
                return(ConstructedValueExpression.Nothing);
            }

            // Pull the value out of the reader into the rawVar
            var rawVar     = context.CreateVariable(typeof(object), "raw");
            var getRawStmt = Expression.Assign(
                rawVar,
                Expression.Call(
                    context.RecordParameter,
                    _getValueMethod,
                    Expression.Constant(column.Index)
                    )
                );

            var rawConvertExpr = MapScalar(context.TargetType, column, rawVar);

            column.MarkMapped();
            return(new ConstructedValueExpression(new[] { getRawStmt }, rawConvertExpr, new[] { rawVar }));
        }
Exemple #2
0
        private ConstructedValueExpression CompileArrayOfScalar(MapTypeContext context, ConstructorInfo constructor, List <ColumnInfo> columns, Type elementType)
        {
            var arrayVar    = context.CreateVariable(context.TargetType, "array");
            var expressions = new List <Expression>();
            var variables   = new List <ParameterExpression>();

            variables.Add(arrayVar);
            expressions.Add(
                Expression.Assign(
                    arrayVar,
                    Expression.New(
                        constructor,
                        Expression.Constant(columns.Count)
                        )
                    )
                );
            for (int i = 0; i < columns.Count; i++)
            {
                var columnState         = context.GetSubstateForColumn(columns[i], elementType, null);
                var getScalarExpression = _scalars.Compile(columnState);
                expressions.AddRange(getScalarExpression.Expressions);
                expressions.Add(
                    Expression.Assign(
                        Expression.ArrayAccess(
                            arrayVar,
                            Expression.Constant(i)
                            ),
                        getScalarExpression.FinalValue
                        )
                    );
                variables.AddRange(getScalarExpression.Variables);
            }

            return(new ConstructedValueExpression(expressions, arrayVar, variables));
        }
        public static ConstructedValueExpression GetMaybeInstantiateDictionaryExpression(MapTypeContext context, ConstructorInfo constructor)
        {
            var newInstance = context.CreateVariable(context.TargetType, "dictionary");

            if (context.GetExisting == null)
            {
                // There's no way to get an existing value, so call the parameterless constructor

                var getNewInstanceExpr = Expression.Assign(
                    newInstance,
                    Expression.New(constructor)
                    );
                return(new ConstructedValueExpression(new[] { getNewInstanceExpr }, newInstance, new[] { newInstance }));
            }

            // Try to get the existing value. If we have it return it. Otherwise call the default
            // parameterless constructor
            var tryGetExistingInstanceExpr = Expression.Assign(
                newInstance,
                Expression.Condition(
                    Expression.Equal(
                        context.GetExisting,
                        Expression.Constant(null)
                        ),
                    Expression.Convert(
                        Expression.New(constructor),
                        context.TargetType
                        ),
                    Expression.Convert(context.GetExisting, context.TargetType)
                    )
                );

            return(new ConstructedValueExpression(new[] { tryGetExistingInstanceExpr }, newInstance, new[] { newInstance }));
        }
Exemple #4
0
        public static ConstructedValueExpression GetMaybeInstantiateCollectionExpression(MapTypeContext context, ConstructorInfo constructor)
        {
            var newInstance = context.CreateVariable(context.TargetType, "list");

            if (context.GetExisting == null)
            {
                // if we don't have an expression to get an existing slot, just create new by
                // calling the default parameterless constructor on the collection type
                var createNewExpr = Expression.Assign(
                    newInstance,
                    Expression.New(constructor)
                    );
                return(new ConstructedValueExpression(new[] { createNewExpr }, newInstance, new[] { newInstance }));
            }

            // Try to get the existing value. If it's null, just create new with the default
            // parameterless constructor. If it's not null we can return it.
            var getExistingExpr = Expression.Assign(
                newInstance,
                Expression.Condition(
                    Expression.Equal(
                        context.GetExisting,
                        Expression.Constant(null)
                        ),
                    Expression.Convert(
                        Expression.New(constructor),
                        context.TargetType
                        ),
                    Expression.Convert(context.GetExisting, context.TargetType)
                    )
                );

            return(new ConstructedValueExpression(new[] { getExistingExpr }, newInstance, new[] { newInstance }));
        }
        private ConstructedValueExpression AddInstantiationExpressionForObjectInstance(MapTypeContext context)
        {
            var instanceVar                    = context.CreateVariable(context.TargetType, "instance");
            var typeInfo                       = context.Settings.GetTypeSettings(context.TargetType);
            var defaultSubtypeInfo             = typeInfo.GetDefault();
            var defaultInstantiationExpression = AddInstantiationExpressionForSpecificType(context, defaultSubtypeInfo, instanceVar);
            var subclasses                     = typeInfo.GetSpecificTypes().ToList();

            // If we have no configured subclass predicates, instantiate the target type directly
            if (subclasses.Count == 0)
            {
                return(new ConstructedValueExpression(defaultInstantiationExpression.Expressions, instanceVar, defaultInstantiationExpression.Variables.Concat(new[] { instanceVar })));
            }

            // If we have configured subclass predicates, unroll the loop and write expressions for
            // all cases. The default case will be executed if no subclass predicates match.
            var endLabel    = context.CreateLabel("haveinstance");
            var expressions = new List <Expression>();

            foreach (var subclass in subclasses.Where(s => s.Predicate != null))
            {
                var instantiateExpressions = AddInstantiationExpressionForSpecificType(context, subclass, instanceVar);
                // Check the subclass predicate. If it matches, we enter into a block where we
                // create the subclass instance and then jump to the end label. Otherwise we
                // fall through to the next subclass.
                expressions.Add(
                    Expression.IfThen(
                        Expression.Call(
                            Expression.Constant(subclass.Predicate.Target),
                            subclass.Predicate.Method,
                            context.RecordParameter
                            ),
                        Expression.Block(
                            instantiateExpressions.Variables,
                            instantiateExpressions.Expressions.Concat(new[] {
                    Expression.Goto(endLabel.Target)
                })
                            )
                        )
                    );
            }
            // A block where we fall back to the default instantiation rules for the type, and then
            // fall through to the endLabel. The block here allows us to scope variables a little
            // more tightly
            expressions.Add(
                Expression.Block(
                    defaultInstantiationExpression.Variables,
                    defaultInstantiationExpression.Expressions
                    )
                );
            expressions.Add(endLabel);

            return(new ConstructedValueExpression(expressions, instanceVar, new[] { instanceVar }));
        }
Exemple #6
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));
        }