Skip to content

Commit f9f582e

Browse files
committed
CSHARP-5043: Support conversion between enum types.
1 parent bf8c4e4 commit f9f582e

File tree

2 files changed

+400
-0
lines changed

2 files changed

+400
-0
lines changed

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

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

57+
if (IsConvertEnumToEnum(expression))
58+
{
59+
return TranslateConvertEnumToEnum(expression, operandTranslation);
60+
}
61+
5762
if (IsConvertToBaseType(sourceType: operandExpression.Type, targetType: expressionType))
5863
{
5964
return TranslateConvertToBaseType(expression, operandTranslation);
@@ -111,6 +116,16 @@ public static AggregationExpression Translate(TranslationContext context, UnaryE
111116
throw new ExpressionNotSupportedException(expression);
112117
}
113118

119+
private static bool IsConvertEnumToEnum(UnaryExpression expression)
120+
{
121+
var sourceType = expression.Operand.Type;
122+
var targetType = expression.Type;
123+
124+
return
125+
sourceType.IsEnumOrNullableEnum(out _, out _) &&
126+
targetType.IsEnumOrNullableEnum(out _, out _);
127+
}
128+
114129
private static bool IsConvertEnumToUnderlyingType(UnaryExpression expression)
115130
{
116131
var sourceType = expression.Operand.Type;
@@ -173,6 +188,46 @@ private static AggregationExpression TranslateConvertToBsonValue(TranslationCont
173188
return new AggregationExpression(expression, operandTranslation.Ast, BsonValueSerializer.Instance);
174189
}
175190

191+
private static AggregationExpression TranslateConvertEnumToEnum(UnaryExpression expression, AggregationExpression operandTranslation)
192+
{
193+
var sourceType = expression.Operand.Type;
194+
var targetType = expression.Type;
195+
196+
if (!sourceType.IsEnumOrNullableEnum(out var sourceEnumType, out _))
197+
{
198+
throw new ExpressionNotSupportedException(expression, because: "source type is not an enum or nullable enum");
199+
}
200+
if (!targetType.IsEnumOrNullableEnum(out var targetEnumType, out _))
201+
{
202+
throw new ExpressionNotSupportedException(expression, because: "target type is not an enum or nullable enum");
203+
}
204+
205+
var sourceSerializer = operandTranslation.Serializer;
206+
IBsonSerializer targetEnumSerializer;
207+
if (targetEnumType == sourceEnumType)
208+
{
209+
targetEnumSerializer = sourceSerializer is INullableSerializer sourceNullableSerializer ?
210+
sourceNullableSerializer.ValueSerializer :
211+
sourceSerializer;
212+
}
213+
else
214+
{
215+
if (sourceSerializer is IHasRepresentationSerializer sourceHasRepresentationSerializer &&
216+
!SerializationHelper.IsNumericRepresentation(sourceHasRepresentationSerializer.Representation))
217+
{
218+
throw new ExpressionNotSupportedException(expression, because: "source enum is not represented as a number");
219+
}
220+
221+
targetEnumSerializer = EnumSerializer.Create(targetEnumType);
222+
}
223+
224+
var targetSerializer = targetType.IsNullable() ?
225+
NullableSerializer.Create(targetEnumSerializer) :
226+
targetEnumSerializer;
227+
228+
return new AggregationExpression(expression, operandTranslation.Ast, targetSerializer);
229+
}
230+
176231
private static AggregationExpression TranslateConvertEnumToUnderlyingType(UnaryExpression expression, AggregationExpression operandTranslation)
177232
{
178233
var sourceType = expression.Operand.Type;

0 commit comments

Comments
 (0)