private Expression BuildProjector(Expression selector, ProjectionBindingContext context) { var selectorNode = selector; if (!(selectorNode is ISerializationExpression)) { var serializer = SerializerBuilder.Build(selector, context.SerializerRegistry); BsonSerializationInfo info; switch (selector.NodeType) { case ExpressionType.MemberInit: case ExpressionType.New: info = new BsonSerializationInfo(null, serializer, serializer.ValueType); break; default: // this occurs when a computed field is used. This is a magic string // that shouldn't ever be reference anywhere else... info = new BsonSerializationInfo("__fld0", serializer, serializer.ValueType); break; } selectorNode = new SerializationExpression(selector, info); } return selectorNode; }
public override Expression Bind(ProjectionExpression projection, ProjectionBindingContext context, MethodCallExpression node, IEnumerable<Expression> arguments) { // OfType is two operations in one. First we create WhereExpression // for the test. Second, we want to issue a conversion projection // using the selector parameter of a ProjectionExpression such that // the conversion will be propogated to all future expressions. var newType = node.Method.GetGenericArguments()[0]; var parameter = Expression.Parameter(projection.Projector.Type); var predicate = Expression.Lambda( Expression.TypeIs(parameter, newType), parameter); var source = BindPredicate(projection, context, projection.Source, predicate); var serializer = context.SerializerRegistry.GetSerializer(newType); var info = new BsonSerializationInfo(null, serializer, newType); var projector = new SerializationExpression( Expression.Convert(projection.Projector, newType), info); return new ProjectionExpression( source, projector); }
/// <summary> /// Registers a serializer with the given expression. /// </summary> /// <param name="node">The expression.</param> /// <param name="serializer">The serializer.</param> public void RegisterExpressionSerializer(Expression node, IBsonSerializer serializer) { _serializationInfoCache[node] = new BsonSerializationInfo( null, serializer, node.Type); }
/// <summary> /// Gets the item serialization info. /// </summary> /// <param name="methodName">Name of the method.</param> /// <param name="serializationInfo">The serialization info.</param> /// <returns>The item BsonSerializationInfo for the expression.</returns> public BsonSerializationInfo GetItemSerializationInfo(string methodName, BsonSerializationInfo serializationInfo) { var arraySerializer = serializationInfo.Serializer as IBsonArraySerializer; if (arraySerializer != null) { var itemSerializationInfo = arraySerializer.GetItemSerializationInfo(); if (itemSerializationInfo != null) { var arrayOptions = serializationInfo.SerializationOptions as ArraySerializationOptions; if (arrayOptions != null) { var itemSerializationOptions = arrayOptions.ItemSerializationOptions; return new BsonSerializationInfo( itemSerializationInfo.ElementName, itemSerializationInfo.Serializer, itemSerializationInfo.NominalType, itemSerializationOptions); } return itemSerializationInfo; } } string message = string.Format("{0} requires that the serializer specified for {1} support items by implementing {2} and returning a non-null result. {3} is the current serializer.", methodName, serializationInfo.ElementName, typeof(IBsonArraySerializer), serializationInfo.Serializer.GetType()); throw new NotSupportedException(message); }
/// <summary> /// Registers a serializer with the given expression. /// </summary> /// <param name="node">The expression.</param> /// <param name="serializer">The serializer.</param> public void RegisterExpressionSerializer(Expression node, IBsonSerializer serializer) { _serializationInfoCache[node] = new BsonSerializationInfo( null, serializer, node.Type, serializer.GetDefaultSerializationOptions()); }
public Expression Bind(ProjectionExpression projection, ProjectionBindingContext context, MethodCallExpression node, IEnumerable<Expression> arguments) { var distinct = new DistinctExpression(projection.Source, projection.Projector); var serializer = SerializerBuilder.Build(projection.Projector, context.SerializerRegistry); var info = new BsonSerializationInfo("_id", serializer, serializer.ValueType); var projector = new SerializationExpression(projection.Projector, info); return new ProjectionExpression( distinct, projector); }
/// <summary> /// Gets the item serialization info. /// </summary> /// <param name="methodName">Name of the method.</param> /// <param name="serializationInfo">The serialization info.</param> /// <returns>The item BsonSerializationInfo for the expression.</returns> public BsonSerializationInfo GetItemSerializationInfo(string methodName, BsonSerializationInfo serializationInfo) { BsonSerializationInfo itemSerializationInfo; if (!TryGetItemSerializationInfo(serializationInfo, out itemSerializationInfo)) { string message = string.Format("{0} requires that the serializer specified for {1} support items by implementing {2} and returning a non-null result. {3} is the current serializer.", methodName, serializationInfo.ElementName, typeof(IBsonArraySerializer), serializationInfo.Serializer.GetType()); throw new NotSupportedException(message); } return itemSerializationInfo; }
/// <summary> /// Tries to get the serialization info for a member. /// </summary> /// <param name="memberName">Name of the member.</param> /// <param name="serializationInfo">The serialization information.</param> /// <returns> /// <c>true</c> if the serialization info exists; otherwise <c>false</c>. /// </returns> public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo) { foreach (var memberMap in _classMap.AllMemberMaps) { if (memberMap.MemberName == memberName) { var elementName = memberMap.ElementName; var serializer = memberMap.GetSerializer(); serializationInfo = new BsonSerializationInfo(elementName, serializer, serializer.ValueType); return(true); } } serializationInfo = null; return(false); }
/// <summary> /// Gets the item serialization info. /// </summary> /// <param name="methodName">Name of the method.</param> /// <param name="serializationInfo">The serialization info.</param> /// <returns>The item BsonSerializationInfo for the expression.</returns> public BsonSerializationInfo GetItemSerializationInfo(string methodName, BsonSerializationInfo serializationInfo) { var itemSerializationInfoProvider = serializationInfo.Serializer as IBsonItemSerializationInfoProvider; if (itemSerializationInfoProvider != null) { var itemSerializationInfo = itemSerializationInfoProvider.GetItemSerializationInfo(); if (itemSerializationInfo != null) { return itemSerializationInfo; } } string message = string.Format("{0} requires that the serializer specified for {1} support items by implementing {2} and returning a non-null result. {3} is the current serializer.", methodName, serializationInfo.ElementName, typeof(IBsonItemSerializationInfoProvider), serializationInfo.Serializer.GetType()); throw new NotSupportedException(message); }
// protected methods /// <summary> /// Registers a member. /// </summary> /// <param name="memberName">The member name.</param> /// <param name="elementName">The element name.</param> /// <param name="serializer">The serializer.</param> protected void RegisterMember(string memberName, string elementName, IBsonSerializer serializer) { if (memberName == null) { throw new ArgumentNullException("memberName"); } if (elementName == null) { throw new ArgumentNullException("elementName"); } if (serializer == null) { throw new ArgumentNullException("serializer"); } var info = new BsonSerializationInfo(elementName, serializer, serializer.ValueType); _memberSerializationInfo.Add(memberName, info); }
/// <summary> /// Merges the new BsonSerializationInfo by taking its properties and concatenating its ElementName. /// </summary> /// <param name="newSerializationInfo">The new info.</param> /// <returns>A new BsonSerializationInfo.</returns> public BsonSerializationInfo Merge(BsonSerializationInfo newSerializationInfo) { string elementName = null; if (_elementName != null && newSerializationInfo._elementName != null) { elementName = _elementName + "." + newSerializationInfo._elementName; } else if (_elementName != null) { elementName = _elementName; } else if (newSerializationInfo._elementName != null) { elementName = newSerializationInfo._elementName; } return(new BsonSerializationInfo( elementName, newSerializationInfo._serializer, newSerializationInfo._nominalType)); }
// protected methods /// <summary> /// Registers a member. /// </summary> /// <param name="memberName">The member name.</param> /// <param name="elementName">The element name.</param> /// <param name="serializer">The serializer.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="serializationOptions">The serialization options.</param> protected void RegisterMember(string memberName, string elementName, IBsonSerializer serializer, Type nominalType, IBsonSerializationOptions serializationOptions) { if (memberName == null) { throw new ArgumentNullException("memberName"); } if (elementName == null) { throw new ArgumentNullException("elementName"); } if (serializer == null) { throw new ArgumentNullException("serializer"); } if (nominalType == null) { throw new ArgumentNullException("nominalType"); } var info = new BsonSerializationInfo(elementName, serializer, nominalType, serializationOptions); _memberSerializationInfo.Add(memberName, info); }
protected internal override Expression VisitCorrelatedGroupBy(CorrelatedGroupByExpression node) { if (_lookup != null && _lookup.Contains(node.CorrelationId)) { var source = Visit(node.Source); var accumulators = new List<SerializationExpression>(); var comparer = new ExpressionComparer(); foreach (var correlatedAccumulator in _lookup[node.CorrelationId]) { var index = accumulators.FindIndex(x => comparer.Compare(x.Expression, correlatedAccumulator.Accumulator)); if (index == -1) { var serializer = _serializerRegistry.GetSerializer(correlatedAccumulator.Type); var info = new BsonSerializationInfo( "__agg" + accumulators.Count, serializer, serializer.ValueType); var serializationExpression = new SerializationExpression(correlatedAccumulator.Accumulator, info); accumulators.Add(serializationExpression); _map[correlatedAccumulator] = serializationExpression; } else { _map[correlatedAccumulator] = accumulators[index]; } } node = node.Update( source, node.Id, accumulators.OfType<Expression>()); } return base.VisitCorrelatedGroupBy(node); }
private Expression BindSelector(ProjectionExpression projection, ProjectionBindingContext context, Expression id, Expression node) { var lambda = ExtensionExpressionVisitor.GetLambda(node); var binder = new AccumulatorBinder(context.GroupMap, context.SerializerRegistry); var serializer = SerializerBuilder.Build(projection.Projector, context.SerializerRegistry); var sequenceSerializer = (IBsonSerializer)Activator.CreateInstance( typeof(ArraySerializer<>).MakeGenericType(projection.Projector.Type), new object[] { serializer }); var sequenceInfo = new BsonSerializationInfo( null, sequenceSerializer, sequenceSerializer.ValueType); var sequenceExpression = new SerializationExpression( lambda.Parameters[1], sequenceInfo); binder.RegisterParameterReplacement(lambda.Parameters[0], id); binder.RegisterParameterReplacement(lambda.Parameters[1], sequenceExpression); var correlationId = Guid.NewGuid(); context.GroupMap.Add(sequenceExpression, correlationId); var bound = binder.Bind(lambda.Body); return CorrelatedAccumulatorRemover.Remove(bound, correlationId); }
public GroupIdExpression(Expression expression, BsonSerializationInfo serializationInfo) { _expression = Ensure.IsNotNull(expression, "expression"); _serializationInfo = Ensure.IsNotNull(serializationInfo, "serializationInfo"); }
private BsonClassMap BuildClassMap(Type type, ProjectionMapping mapping) { if (type == null || type == typeof(object)) { return null; } var baseClassMap = BuildClassMap(type.BaseType, mapping); if (baseClassMap != null) { baseClassMap.Freeze(); } var classMap = new BsonClassMap(type, baseClassMap); foreach (var memberMapping in mapping.Members.Where(x => x.Member.DeclaringType == type)) { var serializationExpression = memberMapping.Expression as ISerializationExpression; if (serializationExpression == null) { var serializer = Build(memberMapping.Expression); var serializationInfo = new BsonSerializationInfo( memberMapping.Member.Name, serializer, GetMemberType(memberMapping.Member)); serializationExpression = new SerializationExpression( memberMapping.Expression, serializationInfo); } var memberMap = classMap.MapMember(memberMapping.Member) .SetSerializer(serializationExpression.SerializationInfo.Serializer) .SetElementName(memberMapping.Member.Name); if (classMap.IdMemberMap == null && serializationExpression is GroupIdExpression) { classMap.SetIdMember(memberMap); } } return classMap; }
/// <summary> /// Tries to get the serialization info for a member. /// </summary> /// <param name="memberName">Name of the member.</param> /// <param name="serializationInfo">The serialization information.</param> /// <returns> /// <c>true</c> if the serialization info exists; otherwise <c>false</c>. /// </returns> public virtual bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo) { return(_memberSerializationInfo.TryGetValue(memberName, out serializationInfo)); }
public void SetValue(object targetResource, string propertyName, object propertyValue) { var resourceType = GetResourceType(targetResource); var annotation = (TypedResourceTypeAnnotation)resourceType.CustomState; var memberMap = annotation.ClassMap.GetMemberMap(propertyName); var serializer = memberMap.GetSerializer(memberMap.MemberType) as IBsonArraySerializer; if (serializer != null) { var itemSerializationInfo = serializer.GetItemSerializationInfo(); var array = itemSerializationInfo.SerializeValues((IEnumerable)propertyValue); var memberMapSerializationInfo = new BsonSerializationInfo(memberMap.ElementName, serializer, memberMap.MemberType, memberMap.SerializationOptions); propertyValue = memberMapSerializationInfo.DeserializeValue(array); } memberMap.Setter(targetResource, propertyValue); if (_rememberedInstances.Contains(targetResource)) { return; } var collection = GetCollection(resourceType); _rememberedInstances.Add(targetResource); _actions.Add(() => collection.Save(resourceType.InstanceType, targetResource)); }
/// <summary> /// Tries the get item serialization information. /// </summary> /// <param name="serializationInfo">The serialization information.</param> /// <param name="itemSerializationInfo">The item serialization information.</param> /// <returns></returns> public bool TryGetItemSerializationInfo(BsonSerializationInfo serializationInfo, out BsonSerializationInfo itemSerializationInfo) { itemSerializationInfo = null; var arraySerializer = serializationInfo.Serializer as IBsonArraySerializer; if (arraySerializer != null && arraySerializer.TryGetItemSerializationInfo(out itemSerializationInfo)) { return true; } return false; }
/// <summary> /// Merges the new BsonSerializationInfo by taking its properties and concatenating its ElementName. /// </summary> /// <param name="newSerializationInfo">The new info.</param> /// <returns>A new BsonSerializationInfo.</returns> public BsonSerializationInfo Merge(BsonSerializationInfo newSerializationInfo) { string elementName = null; if (_elementName != null && newSerializationInfo._elementName != null) { elementName = _elementName + "." + newSerializationInfo._elementName; } else if (_elementName != null) { elementName = _elementName; } else if (newSerializationInfo._elementName != null) { elementName = newSerializationInfo._elementName; } return new BsonSerializationInfo( elementName, newSerializationInfo._serializer, newSerializationInfo._nominalType); }
private IMongoQuery BuildContainsKeyQuery(MethodCallExpression methodCallExpression) { var dictionaryType = methodCallExpression.Object.Type; var dictionaryTypeInfo = dictionaryType.GetTypeInfo(); var implementedInterfaces = new List<Type>(dictionaryTypeInfo.GetInterfaces()); if (dictionaryTypeInfo.IsInterface) { implementedInterfaces.Add(dictionaryType); } Type dictionaryGenericInterface = null; Type dictionaryInterface = null; foreach (var implementedInterface in implementedInterfaces) { var implementedInterfaceTypeInfo = implementedInterface.GetTypeInfo(); if (implementedInterfaceTypeInfo.IsGenericType) { if (implementedInterfaceTypeInfo.GetGenericTypeDefinition() == typeof(IDictionary<,>)) { dictionaryGenericInterface = implementedInterface; } } else if (implementedInterface == typeof(IDictionary)) { dictionaryInterface = implementedInterface; } } if (dictionaryGenericInterface == null && dictionaryInterface == null) { return null; } var arguments = methodCallExpression.Arguments.ToArray(); if (arguments.Length != 1) { return null; } var constantExpression = arguments[0] as ConstantExpression; if (constantExpression == null) { return null; } var key = constantExpression.Value; var serializationInfo = _serializationInfoHelper.GetSerializationInfo(methodCallExpression.Object); var serializer = serializationInfo.Serializer; var dictionarySerializer = serializer as IBsonDictionarySerializer; if (dictionarySerializer == null) { var message = string.Format( "{0} in a LINQ query is only supported for members that are serialized using a serializer that implements IBsonDictionarySerializer.", methodCallExpression.Method.Name); // could be Contains (for IDictionary) or ContainsKey (for IDictionary<TKey, TValue>) throw new NotSupportedException(message); } var keySerializer = dictionarySerializer.KeySerializer; var keySerializationInfo = new BsonSerializationInfo( null, // elementName keySerializer, keySerializer.ValueType); var serializedKey = _serializationInfoHelper.SerializeValue(keySerializationInfo, key); var dictionaryRepresentation = dictionarySerializer.DictionaryRepresentation; switch (dictionaryRepresentation) { case DictionaryRepresentation.ArrayOfDocuments: return Query.EQ(serializationInfo.ElementName + ".k", serializedKey); case DictionaryRepresentation.Document: return Query.Exists(serializationInfo.ElementName + "." + serializedKey.AsString); default: var message = string.Format( "{0} in a LINQ query is only supported for DictionaryRepresentation ArrayOfDocuments or Document, not {1}.", methodCallExpression.Method.Name, // could be Contains (for IDictionary) or ContainsKey (for IDictionary<TKey, TValue>) dictionaryRepresentation); throw new NotSupportedException(message); } }
private BsonValue SerializeValue(BsonSerializationInfo serializationInfo, object value) { var bsonDocument = new BsonDocument(); var bsonWriter = BsonWriter.Create(bsonDocument); bsonWriter.WriteStartDocument(); bsonWriter.WriteName("value"); serializationInfo.Serializer.Serialize(bsonWriter, serializationInfo.NominalType, value, serializationInfo.SerializationOptions); bsonWriter.WriteEndDocument(); return bsonDocument[0]; }
private void TranslatePipeline(PipelineExpression node) { Translate(node.Source); var serializationExpression = node.Projector as ISerializationExpression; var fieldExpression = node.Projector as FieldExpression; // not IFieldExpression if (fieldExpression != null) { var info = new BsonSerializationInfo(fieldExpression.FieldName, fieldExpression.Serializer, fieldExpression.Serializer.ValueType); // We are projecting a field, however the server only responds // with documents. So we'll create a projector that reads a document // and then projects the field out of it. var parameter = Expression.Parameter(typeof(ProjectedObject), "document"); var projector = Expression.Lambda( Expression.Call( parameter, "GetValue", new Type[] { info.Serializer.ValueType }, Expression.Constant(info.ElementName), Expression.Constant(info.Serializer.ValueType.GetDefaultValue(), typeof(object))), parameter); var innerSerializer = new ProjectedObjectDeserializer(new[] { info }); _outputSerializer = (IBsonSerializer)Activator.CreateInstance( typeof(ProjectingDeserializer<,>).MakeGenericType(typeof(ProjectedObject), info.Serializer.ValueType), new object[] { innerSerializer, projector.Compile() }); } else if (serializationExpression != null) { _outputSerializer = serializationExpression.Serializer; } else { throw new NotSupportedException(); } _resultTransformer = node.ResultOperator as IResultTransformer; }
/// <summary> /// Registers the expression serialization information. /// </summary> /// <param name="node">The node.</param> /// <param name="serializationInfo">The serialization information.</param> public void RegisterExpressionSerializationInfo(Expression node, BsonSerializationInfo serializationInfo) { _serializationInfoCache[node] = serializationInfo; }
private BsonArray SerializeValues(BsonSerializationInfo serializationInfo, IEnumerable values) { var bsonDocument = new BsonDocument(); var bsonWriter = BsonWriter.Create(bsonDocument); bsonWriter.WriteStartDocument(); bsonWriter.WriteName("values"); bsonWriter.WriteStartArray(); foreach (var value in values) { serializationInfo.Serializer.Serialize(bsonWriter, serializationInfo.NominalType, value, serializationInfo.SerializationOptions); } bsonWriter.WriteEndArray(); bsonWriter.WriteEndDocument(); return bsonDocument[0].AsBsonArray; }
/// <summary> /// Serializes the value given the serialization information. /// </summary> /// <param name="serializationInfo">The serialization info.</param> /// <param name="value">The value.</param> /// <returns>A BsonValue representing the value serialized using the serializer.</returns> public BsonValue SerializeValue(BsonSerializationInfo serializationInfo, object value) { return serializationInfo.SerializeValue(value); }
/// <summary> /// Serializes the values given the serialization information. /// </summary> /// <param name="serializationInfo">The serialization info.</param> /// <param name="values">The values.</param> /// <returns>A BsonArray representing the values serialized using the serializer.</returns> public BsonArray SerializeValues(BsonSerializationInfo serializationInfo, IEnumerable values) { return serializationInfo.SerializeValues(values); }
/// <summary> /// Tries the get serialization information. /// </summary> /// <param name="node">The node.</param> /// <param name="serializationInfo">The serialization information.</param> /// <returns></returns> public bool TryGetSerializationInfo(Expression node, out BsonSerializationInfo serializationInfo) { var evaluatedNode = PartialEvaluator.Evaluate(node); return BsonSerializationInfoFinder.TryGetSerializationInfo(evaluatedNode, _serializationInfoCache, out serializationInfo); }
private IMongoQuery BuildContainsKeyQuery(MethodCallExpression methodCallExpression) { var dictionaryType = methodCallExpression.Object.Type; var implementedInterfaces = new List<Type>(dictionaryType.GetInterfaces()); if (dictionaryType.IsInterface) { implementedInterfaces.Add(dictionaryType); } Type dictionaryGenericInterface = null; Type dictionaryInterface = null; foreach (var implementedInterface in implementedInterfaces) { if (implementedInterface.IsGenericType) { if (implementedInterface.GetGenericTypeDefinition() == typeof(IDictionary<,>)) { dictionaryGenericInterface = implementedInterface; } } else if (implementedInterface == typeof(IDictionary)) { dictionaryInterface = implementedInterface; } } Type keyNominalType; if (dictionaryGenericInterface != null) { keyNominalType = dictionaryGenericInterface.GetGenericArguments()[0]; // TKey } else if (dictionaryInterface != null) { keyNominalType = typeof(object); } else { return null; } var arguments = methodCallExpression.Arguments.ToArray(); if (arguments.Length != 1) { return null; } var constantExpression = arguments[0] as ConstantExpression; if (constantExpression == null) { return null; } var key = constantExpression.Value; var serializationInfo = _serializationInfoHelper.GetSerializationInfo(methodCallExpression.Object); var dictionarySerializationOptions = (DictionarySerializationOptions)serializationInfo.SerializationOptions ?? DictionarySerializationOptions.Defaults; var keyActualType = (key != null) ? key.GetType() : keyNominalType; var keySerializer = BsonSerializer.LookupSerializer(keyActualType); var keySerializationInfo = new BsonSerializationInfo( null, // elementName keySerializer, keyNominalType, dictionarySerializationOptions.KeyValuePairSerializationOptions.KeySerializationOptions); var serializedKey = _serializationInfoHelper.SerializeValue(keySerializationInfo, key); switch (dictionarySerializationOptions.Representation) { case DictionaryRepresentation.ArrayOfDocuments: return Query.EQ(serializationInfo.ElementName + ".k", serializedKey); case DictionaryRepresentation.Document: return Query.Exists(serializationInfo.ElementName + "." + serializedKey.AsString); default: var message = string.Format( "{0} in a LINQ query is only supported for DictionaryRepresentation ArrayOfDocuments or Document, not {1}.", methodCallExpression.Method.Name, // could be Contains (for IDictionary) or ContainsKey (for IDictionary<TKey, TValue>) dictionarySerializationOptions.Representation); throw new NotSupportedException(message); } }
private Expression BuildFromNonMethodCall(Expression node) { if (node.NodeType == ExpressionType.Constant && node.Type.IsGenericType && node.Type.GetGenericTypeDefinition() == typeof(IMongoQueryable<>)) { var inputType = node.Type.GetGenericArguments()[0]; var serializationInfo = new BsonSerializationInfo( null, _documentSerializer, _documentSerializer.ValueType); return new ProjectionExpression( new SerializationExpression(node, serializationInfo), new SerializationExpression(Expression.Parameter(inputType, "document"), serializationInfo)); } var message = string.Format("The expression tree is not supported: {0}", node.ToString()); throw new NotSupportedException(message); }