Пример #1
0
        /// <summary>
        /// Gets an Expression that gets the value of a POCO field or property.
        /// </summary>
        private Expression GetExpressionToGetValueFromPoco(ParameterExpression poco, PocoColumn column)
        {
            // Start by assuming the database wants the same type that the property is and that we'll just be getting the value from the property:
            // poco.SomeFieldOrProp
            Expression getValueFromPoco = Expression.MakeMemberAccess(poco, column.MemberInfo);

            if (column.MemberInfoType == column.ColumnType)
            {
                return(getValueFromPoco);
            }

            // See if there is a converter available for between the two types
            Delegate converter = _typeConverter.GetToDbConverter(column.MemberInfoType, column.ColumnType);

            if (converter == null)
            {
                // No converter available, at least try a cast:
                // (TColumn) poco.SomeFieldOrProp
                return(Expression.Convert(getValueFromPoco, column.ColumnType));
            }

            // Invoke the converter:
            // converter(poco.SomeFieldOrProp)
            return(Expression.Call(converter.Target == null ? null : Expression.Constant(converter.Target), converter.Method, getValueFromPoco));
        }
Пример #2
0
        /// <summary>
        /// Creates a Func that collects all the values from a POCO (of type T) into an object[], with the values being in the array in the
        /// same order as the POCO's PocoData.Columns collection.
        /// </summary>
        private Func <T, object[]> CreateValueCollector <T>(bool primaryKeyValuesOnly)
        {
            PocoData pocoData = _pocoDataFactory.GetPocoData <T>();

            // Create list to hold the method body and our input parameter, the POCO of type T
            var methodBodyExpressions = new List <Expression>();
            ParameterExpression poco  = Expression.Parameter(pocoData.PocoType, "poco");

            // Figure out which collection of columns to use
            IList <PocoColumn> columns = primaryKeyValuesOnly == false
                                            ? pocoData.Columns
                                            : pocoData.GetPrimaryKeyColumns();

            // Create a variable to hold our return value, and initialize as an object[] of correct size
            var values = Expression.Variable(typeof(object[]), "values");

            methodBodyExpressions.Add(
                // object[] values = new object[... number of columns on POCO ...];
                Expression.Assign(values, Expression.NewArrayBounds(ObjectType, Expression.Constant(columns.Count, IntType))));

            for (var idx = 0; idx < columns.Count; idx++)
            {
                PocoColumn column = columns[idx];

                // Figure out how to get the
                Expression getValueFromPoco = GetExpressionToGetValueFromPoco(poco, column);

                // values[columnIndex] = (object) ... getValueFromPoco ...
                methodBodyExpressions.Add(
                    Expression.Assign(Expression.ArrayAccess(values, Expression.Constant(idx, IntType)),
                                      Expression.Convert(getValueFromPoco, ObjectType))
                    );
            }

            // Return our values array
            methodBodyExpressions.Add(values);

            // Construct the method body, then create a compiled Func for the method
            var methodBody = Expression.Block(new[] { values }, methodBodyExpressions);

            return(Expression.Lambda <Func <T, object[]> >(methodBody, poco).Compile());
        }