Skip to content

Commit 9a8baaa

Browse files
authored
CSHARP-4653: Implement Convert translator for subclasses. (#1101)
1 parent 531fa6e commit 9a8baaa

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ConvertExpressionToAggregationExpressionTranslator.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ public static AggregationExpression Translate(TranslationContext context, UnaryE
5454
return TranslateConvertToBaseType(expression, operandTranslation);
5555
}
5656

57+
if (IsConvertToDerivedType(sourceType: operandExpression.Type, targetType: expressionType))
58+
{
59+
return TranslateConvertToDerivedType(expression, operandTranslation);
60+
}
61+
5762
if (expressionType.IsConstructedGenericType && expressionType.GetGenericTypeDefinition() == typeof(Nullable<>))
5863
{
5964
var valueType = expressionType.GetGenericArguments()[0];
@@ -116,6 +121,11 @@ private static bool IsConvertToBaseType(Type sourceType, Type targetType)
116121
return sourceType.IsSubclassOf(targetType);
117122
}
118123

124+
private static bool IsConvertToDerivedType(Type sourceType, Type targetType)
125+
{
126+
return targetType.IsSubclassOf(sourceType);
127+
}
128+
119129
private static bool IsConvertUnderlyingTypeToEnum(UnaryExpression expression)
120130
{
121131
var sourceType = expression.Operand.Type;
@@ -136,6 +146,13 @@ private static AggregationExpression TranslateConvertToBaseType(UnaryExpression
136146
return new AggregationExpression(expression, operandTranslation.Ast, downcastingSerializer);
137147
}
138148

149+
private static AggregationExpression TranslateConvertToDerivedType(UnaryExpression expression, AggregationExpression operandTranslation)
150+
{
151+
var serializer = BsonSerializer.LookupSerializer(expression.Type);
152+
153+
return new AggregationExpression(expression, operandTranslation.Ast, serializer);
154+
}
155+
139156
private static AggregationExpression TranslateConvertToBsonValue(TranslationContext context, UnaryExpression expression, Expression operand)
140157
{
141158
// handle double conversions like `(BsonValue)(object)x.Anything`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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 FluentAssertions;
17+
using MongoDB.Driver.Linq;
18+
using Xunit;
19+
20+
namespace MongoDB.Driver.Tests.Linq.Linq3ImplementationTests.Translators.ExpressionToAggregationExpressionTranslators
21+
{
22+
public class ConvertExpressionToFilterFieldTranslatorTests : Linq3IntegrationTest
23+
{
24+
[Fact]
25+
public void Should_translate_to_derived_class_on_method_call()
26+
{
27+
var collection = GetCollection();
28+
29+
var queryable = collection.AsQueryable()
30+
.Select(p => new DerivedClass
31+
{
32+
Id = p.Id,
33+
A = ((DerivedClass)p).A.ToUpper()
34+
});
35+
36+
var stages = Translate(collection, queryable);
37+
AssertStages(
38+
stages,
39+
"{ '$project' : { _id : '$_id', A : { '$toUpper' : '$A' } } }");
40+
41+
var result = queryable.Single();
42+
result.Id.Should().Be(1);
43+
result.A.Should().Be("TEST VALUE");
44+
}
45+
46+
[Fact]
47+
public void Should_translate_to_derived_class_on_projection()
48+
{
49+
var collection = GetCollection();
50+
51+
var queryable = collection.AsQueryable()
52+
.Select(p => new DerivedClass()
53+
{
54+
Id = p.Id,
55+
A = ((DerivedClass)p).A
56+
});
57+
58+
var stages = Translate(collection, queryable);
59+
AssertStages(
60+
stages,
61+
"{ '$project' : { _id : '$_id', A : '$A' } }");
62+
63+
var result = queryable.Single();
64+
result.Id.Should().Be(1);
65+
result.A.Should().Be("test value");
66+
}
67+
68+
private IMongoCollection<BaseClass> GetCollection()
69+
{
70+
var collection = GetCollection<BaseClass>("test");
71+
CreateCollection(collection, new DerivedClass()
72+
{
73+
Id = 1,
74+
A = "test value"
75+
});
76+
return collection;
77+
}
78+
79+
private class BaseClass
80+
{
81+
public int Id { get; set; }
82+
}
83+
84+
private class DerivedClass : BaseClass
85+
{
86+
public string A { get; set; }
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)