Skip to content

Commit 706b658

Browse files
committed
Merge branch 'improvement/TopicMappingService-type-checking' into develop
Introduced a new `GetValidatedMappingType()` method which determines and validates the mapping type against a target type (88c7fba). This method is then integrated with both `PopulateTargetCollectionAsync()` (7caa832) and `GetTopicReferenceAsync()` (a31864a) as a way of pre-validating type compatibility _prior_ to mapping the source topic, thus offering a more efficient way of filtering out incompatible types. Previously, the source topics were first mapped and only then filtered out, thus potentially wasting resources mapping topics that would never be used. This could be especially expensive if the models those topics were being mapped to `[Include()]`d associations. This satisfies the requirements of #83.
2 parents 4c4134b + a31864a commit 706b658

2 files changed

Lines changed: 40 additions & 20 deletions

File tree

OnTopic/Mapping/TopicMappingService.cs

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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

OnTopic/Repositories/TopicRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ topic.Parent is not null &&
515515
/*------------------------------------------------------------------------------------------------------------------------
516516
| Execute core implementation
517517
\-----------------------------------------------------------------------------------------------------------------------*/
518-
if (!topic.IsNew && !target.IsNew && !sibling.IsNew) {
518+
if (!topic.IsNew && !target.IsNew && !(sibling?.IsNew?? true)) {
519519
MoveTopic(topic, target, sibling);
520520
}
521521

0 commit comments

Comments
 (0)