Skip to content

Commit 667a3d5

Browse files
committed
use Enum.Parse<TEnum>
1 parent b8f8546 commit 667a3d5

File tree

3 files changed

+28
-33
lines changed

3 files changed

+28
-33
lines changed

src/AutoMapper/Mappers/StringToEnumMapper.cs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,36 @@ namespace AutoMapper.Internal.Mappers
99
using static Expression;
1010
public class StringToEnumMapper : IObjectMapper
1111
{
12-
private static readonly MethodInfo EqualsMethod = typeof(StringToEnumMapper).GetMethod("StringCompareOrdinalIgnoreCase");
13-
private static readonly MethodInfo ParseMethod = typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string), typeof(bool) });
14-
private static readonly MethodInfo IsNullOrEmptyMethod = typeof(string).GetMethod("IsNullOrEmpty");
12+
private static readonly MethodInfo EqualsMethod = typeof(StringToEnumMapper).GetMethod(nameof(StringCompareOrdinalIgnoreCase));
13+
private static readonly MethodInfo ParseMethod = typeof(Enum).StaticGenericMethod("Parse", parametersCount: 2);
14+
private static readonly PropertyInfo Length = typeof(string).GetProperty("Length");
1515
public bool IsMatch(TypePair context) => context.SourceType == typeof(string) && context.DestinationType.IsEnum;
1616
public Expression MapExpression(IGlobalConfiguration configurationProvider, ProfileMap profileMap,
1717
MemberMap memberMap, Expression sourceExpression, Expression destExpression)
1818
{
1919
var destinationType = destExpression.Type;
20+
var ignoreCase = True;
21+
var enumParse = Call(ParseMethod.MakeGenericMethod(destinationType), sourceExpression, ignoreCase);
22+
var enumMember = CheckEnumMember(sourceExpression, destinationType, enumParse, EqualsMethod);
23+
return Condition(Equal(Property(sourceExpression, Length), Zero), Default(destinationType), enumMember);
24+
}
25+
internal static Expression CheckEnumMember(Expression sourceExpression, Type enumType, Expression defaultExpression, MethodInfo comparison = null)
26+
{
2027
List<SwitchCase> switchCases = null;
21-
foreach (var memberInfo in destinationType.GetFields(TypeExtensions.StaticFlags))
28+
foreach (var memberInfo in enumType.GetFields(TypeExtensions.StaticFlags))
2229
{
2330
var attributeValue = memberInfo.GetCustomAttribute<EnumMemberAttribute>()?.Value;
24-
if (attributeValue != null)
31+
if (attributeValue == null)
2532
{
26-
var switchCase = SwitchCase(
27-
ToType(Constant(Enum.ToObject(destinationType, memberInfo.GetValue(null))), destinationType), Constant(attributeValue));
28-
switchCases ??= new();
29-
switchCases.Add(switchCase);
33+
continue;
3034
}
35+
var enumToObject = Constant(Enum.ToObject(enumType, memberInfo.GetValue(null)));
36+
var attributeConstant = Constant(attributeValue);
37+
var (body, testValue) = comparison == null ? (attributeConstant, enumToObject) : (ToType(enumToObject, enumType), attributeConstant);
38+
switchCases ??= new();
39+
switchCases.Add(SwitchCase(body, testValue));
3140
}
32-
var enumParse = ToType(Call(ParseMethod, Constant(destinationType), sourceExpression, True), destinationType);
33-
var parse = switchCases != null ? Switch(sourceExpression, enumParse, EqualsMethod, switchCases) : enumParse;
34-
return Condition(Call(IsNullOrEmptyMethod, sourceExpression), Default(destinationType), parse);
41+
return switchCases == null ? defaultExpression : Switch(sourceExpression, defaultExpression, comparison, switchCases);
3542
}
3643
public static bool StringCompareOrdinalIgnoreCase(string x, string y) => StringComparer.OrdinalIgnoreCase.Equals(x, y);
3744
}
Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
using AutoMapper.Execution;
2-
using System;
3-
using System.Collections.Generic;
42
using System.Linq.Expressions;
5-
using System.Reflection;
6-
using System.Runtime.Serialization;
73
namespace AutoMapper.Internal.Mappers
84
{
95
using static Expression;
@@ -13,23 +9,8 @@ public class ToStringMapper : IObjectMapper
139
public Expression MapExpression(IGlobalConfiguration configurationProvider, ProfileMap profileMap, MemberMap memberMap, Expression sourceExpression, Expression destExpression)
1410
{
1511
var sourceType = sourceExpression.Type;
16-
Expression toStringCall = Call(sourceExpression, ExpressionBuilder.ObjectToString);
17-
return sourceType.IsEnum ? EnumToString(sourceExpression, sourceType, toStringCall) : toStringCall;
18-
}
19-
private static Expression EnumToString(Expression sourceExpression, Type sourceType, Expression toStringCall)
20-
{
21-
List<SwitchCase> switchCases = null;
22-
foreach (var memberInfo in sourceType.GetFields(TypeExtensions.StaticFlags))
23-
{
24-
var attributeValue = memberInfo.GetCustomAttribute<EnumMemberAttribute>()?.Value;
25-
if (attributeValue != null)
26-
{
27-
var switchCase = SwitchCase(Constant(attributeValue), Constant(Enum.ToObject(sourceType, memberInfo.GetValue(null))));
28-
switchCases ??= new();
29-
switchCases.Add(switchCase);
30-
}
31-
}
32-
return switchCases != null ? Switch(sourceExpression, toStringCall, null, switchCases) : toStringCall;
12+
var toStringCall = Call(sourceExpression, ExpressionBuilder.ObjectToString);
13+
return sourceType.IsEnum ? StringToEnumMapper.CheckEnumMember(sourceExpression, sourceType, toStringCall) : toStringCall;
3314
}
3415
}
3516
}

src/UnitTests/Enumerations.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66

77
namespace AutoMapper.Tests
88
{
9+
public class InvalidStringToEnum : AutoMapperSpecBase
10+
{
11+
protected override MapperConfiguration CreateConfiguration() => new(_=> { });
12+
[Fact]
13+
public void Should_throw() => new Action(()=>Map<ConsoleColor>("d")).ShouldThrow<AutoMapperMappingException>().InnerException.Message.ShouldBe(
14+
"Requested value 'd' was not found.");
15+
}
916
public class DefaultEnumValueToString : AutoMapperSpecBase
1017
{
1118
Destination _destination;

0 commit comments

Comments
 (0)