@@ -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 }
0 commit comments