Skip to content

Commit 4ef287c

Browse files
committed
EnumRewriter handles nullable values correctly
1 parent 9fdb392 commit 4ef287c

1 file changed

Lines changed: 26 additions & 3 deletions

File tree

Orm/Xtensive.Orm/Orm/Linq/Expressions/Visitors/EnumRewriter.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ namespace Xtensive.Orm.Linq.Expressions.Visitors
1111
{
1212
internal sealed class EnumRewriter : ExpressionVisitor
1313
{
14+
private readonly static System.Collections.Concurrent.ConcurrentDictionary<Type, Delegate> NullableValueCreators = new();
15+
1416
public static Expression Rewrite(Expression target)
1517
{
1618
return new EnumRewriter().Visit(target);
@@ -41,15 +43,36 @@ private Expression ConvertEnumConstant(ConstantExpression c)
4143
{
4244
if (c.Type.StripNullable().IsEnum) {
4345
var underlyingType = Enum.GetUnderlyingType(c.Type.StripNullable());
44-
if (c.Type.IsNullable())
45-
underlyingType = WellKnownTypes.NullableOfT.CachedMakeGenericType(underlyingType);
46-
var underlyingTypeValue = Convert.ChangeType(c.Value, underlyingType);
46+
47+
object underlyingTypeValue;
48+
if (c.Type.IsNullable()) {
49+
underlyingTypeValue = (c.Value is null)
50+
? null
51+
: CreateNullableUnderlyingValue(c.Value, underlyingType);
52+
}
53+
else {
54+
underlyingTypeValue = Convert.ChangeType(c.Value, underlyingType);
55+
}
4756
var constantExpression = Expression.Constant(underlyingTypeValue);
4857
return Expression.Convert(constantExpression, c.Type);
4958
}
5059
return c;
5160
}
5261

62+
private static object CreateNullableUnderlyingValue(object value, Type underlyingType)
63+
{
64+
var instanceCreator = NullableValueCreators.GetOrAdd(underlyingType, (t) => {
65+
var parameter = Expression.Parameter(underlyingType);
66+
var type = WellKnownTypes.NullableOfT.MakeGenericType(underlyingType);
67+
var ctor = type.GetConstructors()[0];
68+
var body = Expression.New(ctor, parameter);
69+
var instanceCreatorLambda = Expression.Lambda(body, parameter);
70+
return instanceCreatorLambda.Compile();
71+
});
72+
73+
return instanceCreator.DynamicInvoke(value);
74+
}
75+
5376
private EnumRewriter()
5477
{
5578
}

0 commit comments

Comments
 (0)