@@ -978,13 +978,11 @@ configuration.ContentTypeFilter is not null &&
978978 }
979979
980980 //Map child topic to target DTO
981- var childDto = ( object ) childTopic ;
981+ var childDto = ( object ) childTopic ;
982982 if ( ! typeof ( Topic ) . IsAssignableFrom ( listType ) ) {
983- if ( configuration . MapAs != null ) {
984- taskQueue . Add ( MapAsync ( childTopic , configuration . MapAs , configuration . IncludeAssociations , cache ) ) ;
985- }
986- else {
987- taskQueue . Add ( MapAsync ( childTopic , configuration . IncludeAssociations , cache ) ) ;
983+ var mappingType = GetValidatedMappingType ( configuration . MapAs , listType ) ?? GetValidatedMappingType ( childTopic , listType ) ;
984+ if ( mappingType is not null ) {
985+ taskQueue . Add ( MapAsync ( childTopic , mappingType , configuration . IncludeAssociations , cache ) ) ;
988986 }
989987 }
990988 else {
@@ -1009,7 +1007,7 @@ configuration.ContentTypeFilter is not null &&
10091007 | Function: Add to List
10101008 \-----------------------------------------------------------------------------------------------------------------------*/
10111009 void AddToList ( object dto ) {
1012- if ( dto is not null && listType . IsAssignableFrom ( dto . GetType ( ) ) ) {
1010+ if ( dto is not null ) {
10131011 try {
10141012 targetList . Add ( dto ) ;
10151013 }
@@ -1022,6 +1020,34 @@ void AddToList(object dto) {
10221020
10231021 }
10241022
1023+ /*==========================================================================================================================
1024+ | PRIVATE: GET VALIDATED MODEL TYPE
1025+ \-------------------------------------------------------------------------------------------------------------------------*/
1026+ /// <summary>
1027+ /// Given a <paramref name="sourceTopic"/> <see cref="Topic"/>, identifies the target model type associated with it and
1028+ /// validates it against the <paramref name="expectedType"/>.
1029+ /// </summary>
1030+ /// <param name="sourceTopic">The source <see cref="Topic"/> that the target type should be inferred from.</param>
1031+ /// <param name="expectedType">The expected <see cref="Type"/> that the inferred type must be compatible with.</param>
1032+ /// <returns>The inferred target type, if valid, otherwise null.</returns>
1033+ private Type ? GetValidatedMappingType ( Topic sourceTopic , Type expectedType ) =>
1034+ GetValidatedMappingType (
1035+ _typeLookupService . Lookup ( $ "{ sourceTopic . ContentType } TopicViewModel", $ "{ sourceTopic . ContentType } ViewModel") ,
1036+ expectedType
1037+ ) ;
1038+
1039+ /// <summary>
1040+ /// Given a <paramref name="mappingType"/> <see cref="Type"/>, validates it against the <paramref name="expectedType"/>.
1041+ /// If it is compatible, returns the <paramref name="mappingType"/>. Otherwise, returns null.
1042+ /// </summary>
1043+ /// <param name="mappingType">The source <see cref="Type"/> that should be validated.</param>
1044+ /// <param name="expectedType">
1045+ /// The expected <see cref="Type"/> that the <paramref name="mappingType"/> must be compatible with.
1046+ /// </param>
1047+ /// <returns>The <paramref name="mappingType"/>, if valid, otherwise null.</returns>
1048+ private static Type ? GetValidatedMappingType ( Type ? mappingType , Type expectedType ) =>
1049+ expectedType . IsAssignableFrom ( mappingType ) ? mappingType : null ;
1050+
10251051 /*==========================================================================================================================
10261052 | PRIVATE: GET TOPIC REFERENCE
10271053 \-------------------------------------------------------------------------------------------------------------------------*/
@@ -1059,23 +1085,17 @@ MappedTopicCache cache
10591085 /*------------------------------------------------------------------------------------------------------------------------
10601086 | Map referenced topic
10611087 \-----------------------------------------------------------------------------------------------------------------------*/
1062- var topicDto = ( object ? ) null ;
1063- try {
1064- if ( configuration . MapAs != null ) {
1065- topicDto = await MapAsync ( source , configuration . MapAs , configuration . IncludeAssociations , cache ) . ConfigureAwait ( false ) ;
1066- }
1067- else {
1068- topicDto = await MapAsync ( source , configuration . IncludeAssociations , cache ) . ConfigureAwait ( false ) ;
1069- }
1070- }
1071- catch ( InvalidTypeException ) {
1072- //Disregard errors caused by unmapped view models; those are functionally equivalent to IsAssignableFrom() mismatches
1088+ var topicDto = ( object ? ) null ;
1089+ var mappingType = GetValidatedMappingType ( configuration . MapAs , targetType ) ?? GetValidatedMappingType ( source , targetType ) ;
1090+
1091+ if ( mappingType is not null ) {
1092+ topicDto = await MapAsync ( source , mappingType , configuration . IncludeAssociations , cache ) . ConfigureAwait ( false ) ;
10731093 }
10741094
10751095 /*------------------------------------------------------------------------------------------------------------------------
10761096 | Validate results
10771097 \-----------------------------------------------------------------------------------------------------------------------*/
1078- if ( topicDto is null || ! targetType . IsAssignableFrom ( topicDto . GetType ( ) ) ) {
1098+ if ( topicDto is null ) {
10791099 return null ;
10801100 }
10811101
0 commit comments