Esempio n. 1
0
        public Expression CreateExpression(Expression source, Expression reader, int index)
        {
            var jsonTextReaderVariable = Expression.Variable(typeof(JsonTextReader), "jsonTextReader");
            var resultVariable         = Expression.Variable(source.Type, "result");

            var materializer
                = new ComplexTypeMaterializerBuildingExpressionVisitor(jsonTextReaderVariable, typeMappingProvider)
                  .Visit(source);

            return(Expression.Condition(
                       Expression.Call(reader, dbDataReaderIsDBNullMethodInfo, Expression.Constant(index)),
                       Expression.Convert(CreateDefaultValueExpression(source.Type), source.Type),
                       Expression.Call(
                           GetType()
                           .GetMethod(nameof(Materialize), BindingFlags.Static | BindingFlags.NonPublic)
                           .MakeGenericMethod(source.Type),
                           Expression.Call(
                               reader,
                               dbDataReaderGetTextReaderMethodInfo,
                               Expression.Constant(index)),
                           Expression.Lambda(
                               materializer,
                               "JsonMaterializer",
                               new[] { jsonTextReaderVariable }))));
        }
Esempio n. 2
0
            protected override Expression VisitLeaf(Expression node)
            {
                if (node.Type.IsScalarType())
                {
                    var temporaryVariableExpression = Expression.Variable(node.Type);

                    return(Expression.Block(
                               variables: new[]
                    {
                        temporaryVariableExpression
                    },
                               expressions: new[]
                    {
                        readExpression,     // Value
                        Expression.Assign(
                            temporaryVariableExpression,
                            CreateScalarTypeReadExpression(node.Type, jsonTextReader)),
                        readExpression,     // PropertyName | EndObject
                        temporaryVariableExpression,
                    }));
                }
                else if (node.Type.IsSequenceType())
                {
                    var sequenceType = node.Type.GetSequenceType();

                    Expression materializerExpression;

                    if (sequenceType.IsScalarType())
                    {
                        materializerExpression = CreateScalarTypeReadExpression(sequenceType, jsonTextReader);
                    }
                    else
                    {
                        materializerExpression
                            = new ComplexTypeMaterializerBuildingExpressionVisitor(jsonTextReader)
                              .Visit(ExtractProjectionExpression(node));
                    }

                    if (sequenceType.IsScalarType() || sequenceType.IsSequenceType())
                    {
                        var temporaryVariableExpression = Expression.Variable(sequenceType);

                        materializerExpression
                            = Expression.Block(
                                  variables: new[]
                        {
                            temporaryVariableExpression
                        },
                                  expressions: new[]
                        {
                            readExpression,         // PropertyName
                            readExpression,         // Value
                            Expression.Assign(temporaryVariableExpression, materializerExpression),
                            readExpression,         // EndObject
                            temporaryVariableExpression,
                        });
                    }

                    var listVariable     = Expression.Variable(typeof(List <>).MakeGenericType(sequenceType));
                    var listAddMethod    = listVariable.Type.GetRuntimeMethod(nameof(List <object> .Add), new[] { sequenceType });
                    var breakLabelTarget = Expression.Label();

                    var loopBody
                        = Expression.IfThenElse(
                              test: Expression.Equal(
                                  Expression.Property(jsonTextReader, jsonTextReaderTokenTypePropertyInfo),
                                  Expression.Constant(JsonToken.EndArray)),
                              ifTrue: Expression.Break(breakLabelTarget),
                              ifFalse: Expression.Block(
                                  expressions: new[]
                    {
                        Expression.Call(listVariable, listAddMethod, materializerExpression),
                        readExpression,             // StartObject | EndArray
                    }));

                    return(Expression.Block(
                               variables: new[]
                    {
                        listVariable
                    },
                               expressions: new[]
                    {
                        Expression.Assign(listVariable, Expression.New(listVariable.Type)),
                        readExpression,     // StartArray
                        readExpression,     // StartObject
                        Expression.Loop(loopBody, breakLabelTarget),
                        readExpression,     // EndObject | PropertyName
                        node.Type.IsArray
                                ? Expression.Call(
                            enumerableToArrayMethodInfo.MakeGenericMethod(sequenceType),
                            listVariable)
                                : node.Type.IsGenericType(typeof(IQueryable <>))
                                    ? Expression.Call(
                            queryableAsQueryableMethodInfo.MakeGenericMethod(sequenceType),
                            listVariable)
                                    : listVariable as Expression,
                    }));
                }
                else
                {
                    return(new ComplexTypeMaterializerBuildingExpressionVisitor(jsonTextReader)
                           .Visit(ExtractProjectionExpression(node)));
                }
            }
Esempio n. 3
0
            protected override Expression VisitLeaf(Expression node)
            {
                if (node.Type.IsScalarType())
                {
                    var sqlColumnExpression = node as SqlColumnExpression;
                    var typeMapping         = sqlColumnExpression?.TypeMapping ?? typeMappingProvider.FindMapping(node.Type);

                    if (typeMapping?.TargetConversion is null)
                    {
                        return(SqlServerJsonValueReader.CreateReadScalarExpression(
                                   node.Type,
                                   jsonTextReader,
                                   GetNameParts().Last()));
                    }

                    var result
                        = SqlServerJsonValueReader.CreateReadScalarExpression(
                              typeMapping.SourceType,
                              jsonTextReader,
                              GetNameParts().Last());

                    var mappingParameter = typeMapping.TargetConversion.Parameters.Single();

                    result
                        = Expression.Block(
                              variables: new[] { mappingParameter },
                              expressions: new Expression[]
                    {
                        Expression.Assign(mappingParameter, result),
                        Expression.Convert(typeMapping.TargetConversion.Body, node.Type),
                    });

                    return(result);
                }
                else if (node.Type.IsSequenceType())
                {
                    var sequenceType = node.Type.GetSequenceType();
                    var extracted    = ExtractProjectionExpression(node);

                    Expression materializer;

                    if (sequenceType.IsScalarType())
                    {
                        // TODO: Get rid of the need to put this constant multiple places.
                        var name = "$c";

                        switch (extracted)
                        {
                        case SqlColumnExpression sqlColumnExpression:
                        {
                            name = sqlColumnExpression.ColumnName;
                            break;
                        }

                        case SqlAliasExpression sqlAliasExpression:
                        {
                            name = sqlAliasExpression.Alias;
                            break;
                        }
                        }

                        materializer = SqlServerJsonValueReader.CreateReadScalarExpression(sequenceType, jsonTextReader, name);
                    }
                    else
                    {
                        if (extracted == node)
                        {
                            return(SqlServerJsonValueReader.CreateReadOpaqueObjectExpression(node.Type, jsonTextReader));
                        }

                        var visitor = new ComplexTypeMaterializerBuildingExpressionVisitor(jsonTextReader, typeMappingProvider);

                        materializer = visitor.Visit(extracted);
                    }

                    return(CreateSequenceExpression(
                               SqlServerJsonValueReader.CreateReadArrayExpression(
                                   sequenceType,
                                   jsonTextReader,
                                   GetNameParts().LastOrDefault(),
                                   Expression.Lambda(
                                       materializer,
                                       GetMaterializerName(),
                                       Array.Empty <ParameterExpression>())),
                               node.Type));
                }
                else
                {
                    var extracted = ExtractProjectionExpression(node);

                    if (extracted == node)
                    {
                        return(SqlServerJsonValueReader.CreateReadOpaqueObjectExpression(node.Type, jsonTextReader));
                    }

                    var visitor = new ComplexTypeMaterializerBuildingExpressionVisitor(jsonTextReader, typeMappingProvider);
                    var result  = visitor.Visit(extracted);

                    if (result is MethodCallExpression call &&
                        call.Method.DeclaringType == typeof(SqlServerJsonValueReader))
                    {
                        return(result);
                    }

                    return(SqlServerJsonValueReader.CreateReadComplexObjectExpression(
                               node.Type,
                               jsonTextReader,
                               Expression.Lambda(
                                   result,
                                   GetMaterializerName(),
                                   Array.Empty <ParameterExpression>())));
                }
            }