private Expression MaterializeObject(Expression visited) { if (depth > 0 && !extraProperties) { return(SqlServerJsonValueReader.CreateReadComplexPropertyExpression( visited.Type, jsonTextReader, GetNameParts().LastOrDefault(), Expression.Lambda( visited, GetMaterializerName(), Array.Empty <ParameterExpression>()))); } return(visited); }
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>()))); } }