public static AstFilterField Translate(TranslationContext context, MemberExpression memberExpression) { var fieldExpression = ConvertHelper.RemoveConvertToInterface(memberExpression.Expression); var field = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression); var fieldSerializer = field.Serializer; var fieldSerializerType = fieldSerializer.GetType(); if (fieldSerializer is IBsonDocumentSerializer documentSerializer && documentSerializer.TryGetMemberSerializationInfo(memberExpression.Member.Name, out BsonSerializationInfo memberSerializationInfo)) { var subFieldName = memberSerializationInfo.ElementName; var subFieldSerializer = memberSerializationInfo.Serializer; return(field.SubField(subFieldName, subFieldSerializer)); } if (memberExpression.Expression.Type.IsConstructedGenericType && memberExpression.Expression.Type.GetGenericTypeDefinition() == typeof(Nullable <>) && memberExpression.Member.Name == "Value" && fieldSerializerType.IsConstructedGenericType && fieldSerializerType.GetGenericTypeDefinition() == typeof(NullableSerializer <>)) { var valueSerializer = ((IChildSerializerConfigurable)fieldSerializer).ChildSerializer; return(AstFilter.Field(field.Path, valueSerializer)); } throw new ExpressionNotSupportedException(memberExpression); }
public static AstFilterField Translate(TranslationContext context, BinaryExpression expression) { if (expression.NodeType == ExpressionType.ArrayIndex) { var arrayExpression = expression.Left; var arrayField = ExpressionToFilterFieldTranslator.Translate(context, arrayExpression); var indexExpression = expression.Right; var index = indexExpression.GetConstantValue <int>(containingExpression: expression); if (index < 0) { var reason = "negative indexes are not valid"; if (index == -1) { reason += ". To use the positional operator $ use FirstMatchingElement instead of an index value of -1"; // closing period is added by exception } throw new ExpressionNotSupportedException(expression, because: reason); } var itemSerializer = ArraySerializerHelper.GetItemSerializer(arrayField.Serializer); return(arrayField.SubField(index.ToString(), itemSerializer)); } throw new ExpressionNotSupportedException(expression); }
public static AstFilterField Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(MongoEnumerableMethod.AllMatchingElements)) { var sourceExpression = arguments[0]; var field = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression); var identifierExpression = arguments[1]; var identifier = identifierExpression.GetConstantValue <string>(containingExpression: expression); if (identifier == "") { throw new ExpressionNotSupportedException(expression, because: "identifier cannot be an empty string."); } if (field.Serializer is IBsonArraySerializer arraySerializer && arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo)) { var itemSerializer = itemSerializationInfo.Serializer; return(field.SubField($"$[{identifier}]", itemSerializer)); } } throw new ExpressionNotSupportedException(expression); }
public static AstFilterField Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.ElementAt)) { var sourceExpression = arguments[0]; var field = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression); var indexExpression = arguments[1]; var index = indexExpression.GetConstantValue <int>(containingExpression: expression); if (index < 0) { var reason = "negative indexes are not valid"; if (index == -1) { reason += ". To use the positional operator $ use FirstMatchingElement instead of an index value of -1"; // closing period is added by exception } throw new ExpressionNotSupportedException(expression, because: reason); } if (field.Serializer is IBsonArraySerializer arraySerializer && arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo)) { var itemSerializer = itemSerializationInfo.Serializer; return(field.SubField(index.ToString(), itemSerializer)); } } throw new ExpressionNotSupportedException(expression); }
public static AstFilterField Translate(TranslationContext context, BinaryExpression expression) { if (expression.NodeType == ExpressionType.ArrayIndex) { var arrayExpression = expression.Left; var arrayField = ExpressionToFilterFieldTranslator.Translate(context, arrayExpression); var indexExpression = expression.Right; var index = indexExpression.GetConstantValue <int>(containingExpression: expression); var itemSerializer = ArraySerializerHelper.GetItemSerializer(arrayField.Serializer); return(arrayField.SubField(index.ToString(), itemSerializer)); } throw new ExpressionNotSupportedException(expression); }
private static AstFilterField TranslateWithIntIndex(TranslationContext context, MethodCallExpression expression, MethodInfo method, Expression fieldExpression, int index) { var field = ExpressionToFilterFieldTranslator.TranslateEnumerable(context, fieldExpression); if (field.Serializer is IBsonArraySerializer arraySerializer && arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo)) { var itemSerializer = itemSerializationInfo.Serializer; if (method.ReturnType.IsAssignableFrom(itemSerializer.ValueType)) { return(field.SubField(index.ToString(), itemSerializer)); } } throw new ExpressionNotSupportedException(expression); }
public static AstFilterField Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(MongoEnumerableMethod.AllElements)) { var sourceExpression = arguments[0]; var field = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression); if (field.Serializer is IBsonArraySerializer arraySerializer && arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo)) { var itemSerializer = itemSerializationInfo.Serializer; return(field.SubField($"$[]", itemSerializer)); } } throw new ExpressionNotSupportedException(expression); }
private static AstFilterField TranslateWithStringIndex(TranslationContext context, MethodCallExpression expression, MethodInfo method, Expression fieldExpression, string key) { var field = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression); if (typeof(BsonValue).IsAssignableFrom(field.Serializer.ValueType)) { var valueSerializer = BsonValueSerializer.Instance; return(field.SubField(key, valueSerializer)); } if (field.Serializer is IBsonDictionarySerializer dictionarySerializer && dictionarySerializer.DictionaryRepresentation == DictionaryRepresentation.Document) { var valueSerializer = dictionarySerializer.ValueSerializer; if (method.ReturnType.IsAssignableFrom(valueSerializer.ValueType)) { return(field.SubField(key, valueSerializer)); } } throw new ExpressionNotSupportedException(expression); }
public static AstFilterField Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsStatic && method.Name == "First" && arguments.Count == 1) { var enumerableFieldAst = ExpressionToFilterFieldTranslator.TranslateEnumerable(context, arguments[0]); if (enumerableFieldAst.Serializer is IBsonArraySerializer arraySerializer && arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo)) { var itemSerializer = itemSerializationInfo.Serializer; if (method.ReturnType.IsAssignableFrom(itemSerializer.ValueType)) { return(enumerableFieldAst.SubField("0", itemSerializer)); } } } throw new ExpressionNotSupportedException(expression); }
public static AstFilterField Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.ElementAt)) { var sourceExpression = arguments[0]; var field = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression); var indexExpression = arguments[1]; var index = indexExpression.GetConstantValue <int>(containingExpression: expression); if (field.Serializer is IBsonArraySerializer arraySerializer && arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo)) { var itemSerializer = itemSerializationInfo.Serializer; return(field.SubField(index.ToString(), itemSerializer)); } } throw new ExpressionNotSupportedException(expression); }
public static AstFilterField Translate(TranslationContext context, UnaryExpression expression) { if (expression.NodeType == ExpressionType.Convert) { var field = ExpressionToFilterFieldTranslator.Translate(context, expression.Operand); var fieldSerializer = field.Serializer; var fieldType = fieldSerializer.ValueType; var targetType = expression.Type; if (fieldType.IsEnum()) { var enumType = fieldType; var enumUnderlyingType = enumType.GetEnumUnderlyingType(); if (targetType == enumUnderlyingType) { var enumUnderlyingTypeSerializer = EnumUnderlyingTypeSerializer.Create(fieldSerializer); return(AstFilter.Field(field.Path, enumUnderlyingTypeSerializer)); } } if (IsNumericType(targetType)) { IBsonSerializer targetTypeSerializer = expression.Type switch { Type t when t == typeof(byte) => new ByteSerializer(), Type t when t == typeof(short) => new Int16Serializer(), Type t when t == typeof(ushort) => new UInt16Serializer(), Type t when t == typeof(int) => new Int32Serializer(), Type t when t == typeof(uint) => new UInt32Serializer(), Type t when t == typeof(long) => new Int64Serializer(), Type t when t == typeof(ulong) => new UInt64Serializer(), Type t when t == typeof(float) => new SingleSerializer(), Type t when t == typeof(double) => new DoubleSerializer(), Type t when t == typeof(decimal) => new DecimalSerializer(), _ => throw new ExpressionNotSupportedException(expression) }; if (fieldSerializer is IRepresentationConfigurable representationConfigurableFieldSerializer && targetTypeSerializer is IRepresentationConfigurable representationConfigurableTargetTypeSerializer) { var fieldRepresentation = representationConfigurableFieldSerializer.Representation; if (fieldRepresentation == BsonType.String) { targetTypeSerializer = representationConfigurableTargetTypeSerializer.WithRepresentation(fieldRepresentation); } } if (fieldSerializer is IRepresentationConverterConfigurable converterConfigurableFieldSerializer && targetTypeSerializer is IRepresentationConverterConfigurable converterConfigurableTargetTypeSerializer) { targetTypeSerializer = converterConfigurableTargetTypeSerializer.WithConverter(converterConfigurableFieldSerializer.Converter); } return(AstFilter.Field(field.Path, targetTypeSerializer)); } if (targetType.IsConstructedGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable <>)) { var nullableValueType = targetType.GetGenericArguments()[0]; if (nullableValueType == fieldType) { var nullableSerializerType = typeof(NullableSerializer <>).MakeGenericType(nullableValueType); var nullableSerializer = (IBsonSerializer)Activator.CreateInstance(nullableSerializerType, fieldSerializer); return(AstFilter.Field(field.Path, nullableSerializer)); } if (fieldType.IsConstructedGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable <>)) { var fieldValueType = fieldType.GetGenericArguments()[0]; if (fieldValueType.IsEnum()) { var enumUnderlyingType = fieldValueType.GetEnumUnderlyingType(); if (nullableValueType == enumUnderlyingType) { var fieldSerializerType = fieldSerializer.GetType(); if (fieldSerializerType.IsConstructedGenericType && fieldSerializerType.GetGenericTypeDefinition() == typeof(NullableSerializer <>)) { var enumSerializer = ((IChildSerializerConfigurable)fieldSerializer).ChildSerializer; var enumUnderlyingTypeSerializer = EnumUnderlyingTypeSerializer.Create(enumSerializer); var nullableSerializerType = typeof(NullableSerializer <>).MakeGenericType(nullableValueType); var nullableSerializer = (IBsonSerializer)Activator.CreateInstance(nullableSerializerType, enumUnderlyingTypeSerializer); return(AstFilter.Field(field.Path, nullableSerializer)); } } } } } } throw new ExpressionNotSupportedException(expression); }