Beispiel #1
0
        /// <summary>
        /// Creates a mapper Func for a projection.
        /// </summary>
        private Func <Row, T> CreateMapperForProjection <T>(RowSet rows, NewTypeProjection projection)
        {
            ICollection <Expression> methodBodyExpressions = new LinkedList <Expression>();
            // The input parameter for our Func<Row, T>, a C* Row
            ParameterExpression row = Expression.Parameter(CassandraRowType, "row");
            // poco variable
            ParameterExpression poco  = Expression.Variable(typeof(T), "poco");
            var constructorParameters = projection.ConstructorInfo.GetParameters();
            var columnIndex           = 0;

            if (constructorParameters.Length == 0)
            {
                // Use default constructor
                // T poco = new T()
                methodBodyExpressions.Add(Expression.Assign(poco, Expression.New(projection.ConstructorInfo)));
            }
            else
            {
                var parameterExpressions = new List <Expression>();
                if (constructorParameters.Length > rows.Columns.Length)
                {
                    throw new IndexOutOfRangeException(string.Format("Expected at least {0} column(s), obtained {1}",
                                                                     constructorParameters.Length, rows.Columns.Length));
                }
                for (columnIndex = 0; columnIndex < constructorParameters.Length; columnIndex++)
                {
                    var c         = rows.Columns[columnIndex];
                    var param     = constructorParameters[columnIndex];
                    var getValueT = GetExpressionToGetColumnValueFromRow(row, c, param.ParameterType);
                    parameterExpressions.Add(getValueT);
                }
                // T poco = new T(param1, param2, ...)
                methodBodyExpressions.Add(Expression.Assign(poco,
                                                            Expression.New(projection.ConstructorInfo, parameterExpressions)));
            }
            // Fill the rest of members with the rest of the column values
            // ReSharper disable once GenericEnumeratorNotDisposed
            var membersEnumerator = projection.Members.GetEnumerator();

            while (membersEnumerator.MoveNext() && columnIndex < rows.Columns.Length)
            {
                var member         = membersEnumerator.Current;
                var c              = rows.Columns[columnIndex];
                var memberType     = GetUnderlyingType(member);
                var getColumnValue = GetExpressionToGetColumnValueFromRow(row, c, memberType);
                // poco.SomeFieldOrProp = ... getColumnValue call ...
                var getValueAndAssign = Expression.Assign(
                    Expression.MakeMemberAccess(poco, member), getColumnValue);
                // Start with an expression that does nothing if the row is null
                Expression ifRowValueIsNull = Expression.Empty();
                // For collections, make an effort to return an empty collection instead of null
                if (TryGetCreateEmptyCollectionExpression(c, memberType, out Expression createEmptyCollection))
                {
                    // poco.SomeFieldOrProp = ... createEmptyCollection ...
                    ifRowValueIsNull = Expression.Assign(Expression.MakeMemberAccess(poco, member), createEmptyCollection);
                }

                var columnIndexExpression = Expression.Constant(columnIndex, IntType);
                //Expression equivalent to
                // if (row.IsNull(columnIndex) == false) => getValueAndAssign ...
                // else => ifRowIsNull ...
                methodBodyExpressions.Add(Expression.IfThenElse(
                                              Expression.IsFalse(Expression.Call(row, IsNullMethod, columnIndexExpression)),
                                              getValueAndAssign,
                                              ifRowValueIsNull));
                columnIndex++;
            }
            // The last expression in the method body is the return value, so put our new POCO at the end
            methodBodyExpressions.Add(poco);
            // Create a block expression for the method body expressions
            var methodBody = Expression.Block(new [] { poco }, methodBodyExpressions);

            // Return compiled expression
            return(Expression.Lambda <Func <Row, T> >(methodBody, row).Compile());
        }
Beispiel #2
0
 protected override Expression VisitNew(NewExpression node)
 {
     Projection = new NewTypeProjection(node.Constructor);
     return(node);
 }