public static IReadOnlyList <IFieldExpression> Gather(Expression node)
            {
                var gatherer = new SerializationExpressionGatherer();

                gatherer.Visit(node);
                return(gatherer._fieldExpressions);
            }
        public static RenderedProjectionDefinition <TProjection> Translate <TDocument, TProjection>(Expression <Func <TDocument, TProjection> > projector, IBsonSerializer <TDocument> parameterSerializer, IBsonSerializerRegistry serializerRegistry)
        {
            var bindingContext     = new PipelineBindingContext(serializerRegistry);
            var documentExpression = new DocumentExpression(parameterSerializer);

            bindingContext.AddExpressionMapping(projector.Parameters[0], documentExpression);

            var node = PartialEvaluator.Evaluate(projector.Body);

            node = Transformer.Transform(node);
            node = bindingContext.Bind(node, isClientSideProjection: true);
            node = FieldExpressionFlattener.FlattenFields(node);

            BsonDocument projectionDocument = null;
            IBsonSerializer <TProjection> serializer;

            if (node is DocumentExpression)
            {
                serializer = new ProjectingDeserializer <TDocument, TProjection>(parameterSerializer, projector.Compile());
            }
            else
            {
                var candidateFields   = SerializationExpressionGatherer.Gather(node);
                var fields            = GetUniqueFieldsByHierarchy(candidateFields);
                var serializationInfo = fields.Select(x => new BsonSerializationInfo(x.FieldName, x.Serializer, x.Serializer.ValueType)).ToList();

                var projectedObjectExpression = Expression.Parameter(typeof(ProjectedObject), "document");
                var translator = new FindProjectionTranslator(documentExpression, projectedObjectExpression, fields);
                var translated = translator.Visit(node);
                if (translator._fullDocument)
                {
                    serializer = new ProjectingDeserializer <TDocument, TProjection>(parameterSerializer, projector.Compile());
                }
                else
                {
                    var newProjector = Expression.Lambda <Func <ProjectedObject, TProjection> >(
                        translated,
                        projectedObjectExpression);

                    projectionDocument = GetProjectionDocument(serializationInfo);
                    var projectedObjectSerializer = new ProjectedObjectDeserializer(serializationInfo);
                    serializer = new ProjectingDeserializer <ProjectedObject, TProjection>(projectedObjectSerializer, newProjector.Compile());
                }
            }

            return(new RenderedProjectionDefinition <TProjection>(projectionDocument, serializer));
        }
Ejemplo n.º 3
0
            protected override Expression VisitMethodCall(MethodCallExpression node)
            {
                if (!IsLinqMethod(node, "Select", "SelectMany"))
                {
                    return(base.VisitMethodCall(node));
                }

                var source = node.Arguments[0] as SerializationExpression;

                if (source != null)
                {
                    var fields = SerializationExpressionGatherer.Gather(node.Arguments[1]);
                    if (fields.Any(x => x.SerializationInfo.ElementName.StartsWith(source.SerializationInfo.ElementName)))
                    {
                        _serializationExpressions.AddRange(fields);
                        return(node);
                    }
                }

                return(base.VisitMethodCall(node));
            }
Ejemplo n.º 4
0
        public static RenderedProjectionDefinition <TProjection> Translate <TDocument, TProjection>(Expression <Func <TDocument, TProjection> > projector, IBsonSerializer <TDocument> parameterSerializer)
        {
            var parameterSerializationInfo = new BsonSerializationInfo(null, parameterSerializer, parameterSerializer.ValueType);
            var parameterExpression        = new SerializationExpression(projector.Parameters[0], parameterSerializationInfo);
            var binder = new SerializationInfoBinder(BsonSerializer.SerializerRegistry);

            binder.RegisterParameterReplacement(projector.Parameters[0], parameterExpression);
            var normalizedBody  = Transformer.Transform(projector.Body);
            var evaluatedBody   = PartialEvaluator.Evaluate(normalizedBody);
            var boundExpression = binder.Bind(evaluatedBody);
            var candidateFields = SerializationExpressionGatherer.Gather(boundExpression);

            var fields = GetUniqueFieldsByHierarchy(candidateFields);

            var serializationInfo = fields.Select(x => x.SerializationInfo).ToList();

            var replacementParameter = Expression.Parameter(typeof(ProjectedObject), "document");

            var translator   = new FindProjectionTranslator(projector.Parameters[0], replacementParameter, fields);
            var newProjector = Expression.Lambda <Func <ProjectedObject, TProjection> >(
                translator.Visit(boundExpression),
                replacementParameter);

            BsonDocument projectionDocument;
            IBsonSerializer <TProjection> serializer;

            if (translator._fullDocument)
            {
                projectionDocument = null;
                serializer         = new ProjectingDeserializer <TDocument, TProjection>(parameterSerializer, projector.Compile());
            }
            else
            {
                projectionDocument = GetProjectionDocument(serializationInfo);
                var projectedObjectSerializer = new ProjectedObjectDeserializer(serializationInfo);
                serializer = new ProjectingDeserializer <ProjectedObject, TProjection>(projectedObjectSerializer, newProjector.Compile());
            }

            return(new RenderedProjectionDefinition <TProjection>(projectionDocument, serializer));
        }