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)); }