11namespace AgileObjects . AgileMapper . Api . Configuration
22{
3+ using System . Collections . Generic ;
4+ using System . Globalization ;
5+ using System . Linq ;
36 using AgileMapper . Configuration ;
7+ using Extensions ;
48 using NetStandardPolyfills ;
59 using ReadableExpressions . Extensions ;
610
1115 public class EnumPairSpecifier < TFirstEnum >
1216 {
1317 private readonly MappingConfigInfo _configInfo ;
14- private readonly TFirstEnum _firstEnumMember ;
18+ private readonly TFirstEnum [ ] _firstEnumMembers ;
1519
1620 private EnumPairSpecifier (
1721 MapperContext mapperContext ,
18- TFirstEnum firstEnumMember )
22+ TFirstEnum [ ] firstEnumMembers )
1923 {
2024 _configInfo = MappingConfigInfo . AllRuleSetsSourceTypesAndTargetTypes ( mapperContext ) ;
21- _firstEnumMember = firstEnumMember ;
25+ _firstEnumMembers = firstEnumMembers ;
2226 }
2327
2428 #region Factory Method
2529
2630 internal static EnumPairSpecifier < TFirstEnum > For (
2731 MapperContext mapperContext ,
28- TFirstEnum firstEnumMember )
32+ TFirstEnum [ ] firstEnumMembers )
2933 {
3034 ThrowIfNotEnumType < TFirstEnum > ( ) ;
35+ ThrowIfEmpty ( firstEnumMembers ) ;
3136
32- return new EnumPairSpecifier < TFirstEnum > ( mapperContext , firstEnumMember ) ;
37+ return new EnumPairSpecifier < TFirstEnum > ( mapperContext , firstEnumMembers ) ;
3338 }
3439
3540 private static void ThrowIfNotEnumType < T > ( )
@@ -41,30 +46,53 @@ private static void ThrowIfNotEnumType<T>()
4146 }
4247 }
4348
49+ private static void ThrowIfEmpty ( ICollection < TFirstEnum > firstEnumMembers )
50+ {
51+ if ( firstEnumMembers . None ( ) )
52+ {
53+ throw new MappingConfigurationException ( "Source enum members must be provided." ) ;
54+ }
55+ }
56+
4457 #endregion
4558
4659 /// <summary>
4760 /// Configure this mapper to map the specified first enum member to the given <paramref name="secondEnumMember"/>.
4861 /// </summary>
4962 /// <typeparam name="TSecondEnum">The type of the second enum being paired.</typeparam>
5063 /// <param name="secondEnumMember">The second enum member in the pair.</param>
51- /// <returns>A MappingConfigContinuation to enable further global mapping configuration.</returns>
52- public MappingConfigContinuation < object , object > With < TSecondEnum > ( TSecondEnum secondEnumMember )
53- where TSecondEnum : struct
64+ public void With < TSecondEnum > ( TSecondEnum secondEnumMember ) where TSecondEnum : struct
65+ => With ( new [ ] { secondEnumMember } ) ;
66+
67+ /// <summary>
68+ /// Configure this mapper to map the previously-specified set of enum members to the given
69+ /// <paramref name="secondEnumMembers"/>.
70+ /// </summary>
71+ /// <typeparam name="TSecondEnum">The type of the second enum being paired.</typeparam>
72+ /// <param name="secondEnumMembers">The second set of enum members in the pairs.</param>
73+ public void With < TSecondEnum > ( params TSecondEnum [ ] secondEnumMembers ) where TSecondEnum : struct
5474 {
5575 ThrowIfNotEnumType < TSecondEnum > ( ) ;
5676 ThrowIfSameTypes < TSecondEnum > ( ) ;
77+ ThrowIfEmpty ( secondEnumMembers ) ;
78+ ThrowIfDifferingNumbers ( secondEnumMembers ) ;
5779
58- var firstToSecondPairing = EnumMemberPair . For ( _firstEnumMember , secondEnumMember ) ;
59- var secondToFirstPairing = EnumMemberPair . For ( secondEnumMember , _firstEnumMember ) ;
80+ for ( var i = 0 ; i < _firstEnumMembers . Length ; i ++ )
81+ {
82+ var firstEnumMember = _firstEnumMembers [ i ] ;
83+ var secondEnumMember = secondEnumMembers [ i ] ;
6084
61- _configInfo . MapperContext . ValueConverters . Add ( firstToSecondPairing . ValueConverter ) ;
62- _configInfo . MapperContext . ValueConverters . Add ( secondToFirstPairing . ValueConverter ) ;
85+ ThrowIfAlreadyPaired ( firstEnumMember , secondEnumMember ) ;
6386
64- _configInfo . MapperContext . UserConfigurations . Add ( firstToSecondPairing ) ;
65- _configInfo . MapperContext . UserConfigurations . Add ( secondToFirstPairing ) ;
87+ var firstToSecondPairing = EnumMemberPair . For ( firstEnumMember , secondEnumMember ) ;
88+ var secondToFirstPairing = EnumMemberPair . For ( secondEnumMember , firstEnumMember ) ;
6689
67- return new MappingConfigContinuation < object , object > ( _configInfo ) ;
90+ _configInfo . MapperContext . ValueConverters . Add ( firstToSecondPairing . ValueConverter ) ;
91+ _configInfo . MapperContext . ValueConverters . Add ( secondToFirstPairing . ValueConverter ) ;
92+
93+ _configInfo . MapperContext . UserConfigurations . Add ( firstToSecondPairing ) ;
94+ _configInfo . MapperContext . UserConfigurations . Add ( secondToFirstPairing ) ;
95+ }
6896 }
6997
7098 private static void ThrowIfSameTypes < TSecondEnum > ( )
@@ -75,5 +103,69 @@ private static void ThrowIfSameTypes<TSecondEnum>()
75103 "Enum pairing can only be configured between different enum types." ) ;
76104 }
77105 }
106+
107+ private static void ThrowIfEmpty < TSecondEnum > ( ICollection < TSecondEnum > secondEnumMembers )
108+ {
109+ if ( secondEnumMembers . None ( ) )
110+ {
111+ throw new MappingConfigurationException ( "Target enum members must be provided." ) ;
112+ }
113+ }
114+
115+ // ReSharper disable once UnusedParameter.Local
116+ private void ThrowIfDifferingNumbers < TSecondEnum > ( ICollection < TSecondEnum > secondEnumMembers )
117+ {
118+ if ( _firstEnumMembers . Length != secondEnumMembers . Count )
119+ {
120+ throw new MappingConfigurationException (
121+ "The same number of first and second enum values must be provided." ) ;
122+ }
123+ }
124+
125+ private void ThrowIfAlreadyPaired < TSecondEnum > ( TFirstEnum firstEnumMember , TSecondEnum secondEnumMember )
126+ {
127+ var firstEnumMemberName = firstEnumMember . ToString ( ) ;
128+ var secondEnumMemberName = secondEnumMember . ToString ( ) ;
129+
130+ var relevantPairings = _configInfo
131+ . MapperContext
132+ . UserConfigurations
133+ . EnumParings
134+ . Where ( ep => ep . IsFor ( typeof ( TFirstEnum ) , typeof ( TSecondEnum ) ) )
135+ . ToArray ( ) ;
136+
137+ if ( relevantPairings . None ( ) )
138+ {
139+ return ;
140+ }
141+
142+ var confictingPairing = relevantPairings
143+ . FirstOrDefault ( ep => ep . FirstEnumMemberName == firstEnumMemberName ) ;
144+
145+ if ( confictingPairing != null )
146+ {
147+ throw new MappingConfigurationException ( string . Format (
148+ CultureInfo . InvariantCulture ,
149+ "{0}.{1} is already paired with {2}.{3}" ,
150+ typeof ( TFirstEnum ) . Name ,
151+ firstEnumMemberName ,
152+ typeof ( TSecondEnum ) . Name ,
153+ confictingPairing . SecondEnumMemberName ) ) ;
154+ }
155+
156+ confictingPairing = relevantPairings
157+ . FirstOrDefault ( ep => ep . SecondEnumMemberName == secondEnumMemberName ) ;
158+
159+ if ( confictingPairing != null )
160+ {
161+ throw new MappingConfigurationException ( string . Format (
162+ CultureInfo . InvariantCulture ,
163+ "{0}.{1} is already paired with {2}.{3}" ,
164+ typeof ( TSecondEnum ) . Name ,
165+ secondEnumMemberName ,
166+ typeof ( TFirstEnum ) . Name ,
167+ confictingPairing . FirstEnumMemberName ) ) ;
168+ }
169+ }
78170 }
79171}
0 commit comments