Skip to content

Commit c249251

Browse files
committed
CSHARP-4809: If a string serializer doesn't implement IHasRepresentationSerializer don't assume string values are actually represented as strings.
1 parent bd4c331 commit c249251

File tree

2 files changed

+104
-2
lines changed

2 files changed

+104
-2
lines changed

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,8 +519,11 @@ private static (AstFilterField, Modifiers) TranslateField(TranslationContext con
519519
{
520520
var field = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);
521521

522-
if (field.Serializer is IRepresentationConfigurable representationConfigurable &&
523-
representationConfigurable.Representation != BsonType.String)
522+
if (field.Serializer is not IHasRepresentationSerializer hasRepresentationSerializer)
523+
{
524+
throw new ExpressionNotSupportedException(fieldExpression, expression, because: $"it was not possible to determine whether field \"{field.Path}\" is represented as a string");
525+
}
526+
if (hasRepresentationSerializer.Representation != BsonType.String)
524527
{
525528
throw new ExpressionNotSupportedException(fieldExpression, expression, because: $"field \"{field.Path}\" is not represented as a string");
526529
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using FluentAssertions;
18+
using MongoDB.Bson;
19+
using MongoDB.Bson.Serialization;
20+
using MongoDB.Bson.Serialization.Attributes;
21+
using MongoDB.Bson.Serialization.Serializers;
22+
using MongoDB.Driver.Linq;
23+
using MongoDB.TestHelpers.XunitExtensions;
24+
using Xunit;
25+
26+
namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Jira
27+
{
28+
public class CSharp4809Tests : Linq3IntegrationTest
29+
{
30+
[Theory]
31+
[ParameterAttributeData]
32+
public void Filter_by_Id_with_custom_serializer_should_work(
33+
[Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
34+
{
35+
var collection = GetCollection(linqProvider);
36+
var id = "111111111111111111111111";
37+
38+
var filter = Builders<RootDocument>.Filter.Where(x => x.Id == id);
39+
40+
var renderedFilter = filter.Render(collection.DocumentSerializer, BsonSerializer.SerializerRegistry, linqProvider);
41+
renderedFilter.Should().Be("{ _id : ObjectId('111111111111111111111111' ) }");
42+
43+
var result = collection.FindSync(filter).Single();
44+
result.X.Should().Be(1);
45+
}
46+
47+
private IMongoCollection<RootDocument> GetCollection(LinqProvider linqProvider)
48+
{
49+
var collection = GetCollection<RootDocument>("test", linqProvider);
50+
CreateCollection(
51+
collection,
52+
new RootDocument { Id = "111111111111111111111111", X = 1 },
53+
new RootDocument { Id = "222222222222222222222222", X = 2 });
54+
return collection;
55+
}
56+
57+
private class RootDocument
58+
{
59+
[BsonSerializer(typeof(CustomStringRepresentedAsObjectIdSerializer))]
60+
public string Id { get; set; }
61+
public int X { get; set; }
62+
}
63+
64+
// This custom serializer is a slightly modified version of the custom serializer in the JIRA ticket
65+
// note: normally this serializer would implement IHasRepresentationSerializer
66+
// but for testing purposes we deliberately chose not to implement it
67+
public class CustomStringRepresentedAsObjectIdSerializer : SerializerBase<string>
68+
{
69+
public override string Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
70+
{
71+
BsonType type = context.Reader.GetCurrentBsonType();
72+
switch (type)
73+
{
74+
case BsonType.ObjectId: return context.Reader.ReadObjectId().ToString();
75+
default:
76+
var message = $"Cannot convert a {type} to a String.";
77+
throw new NotSupportedException(message);
78+
}
79+
}
80+
81+
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, string value)
82+
{
83+
context.Writer.WriteObjectId(ToObjectId(value));
84+
}
85+
86+
private static ObjectId ToObjectId(string source)
87+
{
88+
if (ObjectId.TryParse(source, out ObjectId returnId))
89+
{
90+
return returnId;
91+
}
92+
else
93+
{
94+
return ObjectId.Empty;
95+
}
96+
}
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)