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)); }
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 = Normalizer.Normalize(projector.Body); var evaluatedBody = PartialEvaluator.Evaluate(normalizedBody); var boundExpression = binder.Bind(evaluatedBody); var candidateFields = FieldGatherer.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)); }