55\=============================================================================================================================*/
66using System ;
77using System . Collections ;
8- using System . Collections . Concurrent ;
98using System . Collections . Generic ;
109using System . Diagnostics . CodeAnalysis ;
1110using System . Linq ;
1211using System . Reflection ;
1312using System . Threading . Tasks ;
1413using OnTopic . Attributes ;
14+ using OnTopic . Internal . Collections ;
1515using OnTopic . Internal . Diagnostics ;
1616using OnTopic . Internal . Mapping ;
1717using OnTopic . Internal . Reflection ;
@@ -60,7 +60,7 @@ public TopicMappingService(ITopicRepository topicRepository, ITypeLookupService
6060 /// <inheritdoc />
6161 [ return : NotNullIfNotNull ( "topic" ) ]
6262 public async Task < object ? > MapAsync ( Topic ? topic , Relationships relationships = Relationships . All ) =>
63- await MapAsync ( topic , relationships , new ConcurrentDictionary < int , object > ( ) ) . ConfigureAwait ( false ) ;
63+ await MapAsync ( topic , relationships , new MappedTopicCache ( ) ) . ConfigureAwait ( false ) ;
6464
6565 /// <summary>
6666 /// Given a topic, will identify any View Models named, by convention, "{ContentType}TopicViewModel" and populate them
@@ -90,7 +90,7 @@ public TopicMappingService(ITopicRepository topicRepository, ITypeLookupService
9090 private async Task < object ? > MapAsync (
9191 Topic ? topic ,
9292 Relationships relationships ,
93- ConcurrentDictionary < int , object > cache ,
93+ MappedTopicCache cache ,
9494 string ? attributePrefix = null
9595 ) {
9696
@@ -104,8 +104,8 @@ public TopicMappingService(ITopicRepository topicRepository, ITypeLookupService
104104 /*------------------------------------------------------------------------------------------------------------------------
105105 | Handle cached objects
106106 \-----------------------------------------------------------------------------------------------------------------------*/
107- if ( cache . TryGetValue ( topic . Id , out var dto ) ) {
108- return dto ;
107+ if ( cache . TryGetValue ( topic . Id , out var cacheEntry ) ) {
108+ return cacheEntry . MappedTopic ;
109109 }
110110
111111 /*------------------------------------------------------------------------------------------------------------------------
@@ -146,7 +146,7 @@ public TopicMappingService(ITopicRepository topicRepository, ITypeLookupService
146146 /// <inheritdoc />
147147 public async Task < object ? > MapAsync ( Topic ? topic , object target , Relationships relationships = Relationships . All ) {
148148 Contract . Requires ( target , nameof ( target ) ) ;
149- return await MapAsync ( topic , target , relationships , new ConcurrentDictionary < int , object > ( ) ) . ConfigureAwait ( false ) ;
149+ return await MapAsync ( topic , target , relationships , new MappedTopicCache ( ) ) . ConfigureAwait ( false ) ;
150150 }
151151
152152 /// <summary>
@@ -166,10 +166,10 @@ public TopicMappingService(ITopicRepository topicRepository, ITypeLookupService
166166 /// The target view model with the properties appropriately mapped.
167167 /// </returns>
168168 private async Task < object > MapAsync (
169- Topic ? topic ,
170- object target ,
171- Relationships relationships ,
172- ConcurrentDictionary < int , object > cache ,
169+ Topic ? topic ,
170+ object target ,
171+ Relationships relationships ,
172+ MappedTopicCache cache ,
173173 string ? attributePrefix = null
174174 ) {
175175
@@ -190,11 +190,17 @@ private async Task<object> MapAsync(
190190 /*------------------------------------------------------------------------------------------------------------------------
191191 | Handle cached objects
192192 \-----------------------------------------------------------------------------------------------------------------------*/
193- if ( cache . TryGetValue ( topic . Id , out var dto ) ) {
194- return dto ;
193+ if ( cache . TryGetValue ( topic . Id , out var cacheEntry ) ) {
194+ return cacheEntry . MappedTopic ;
195195 }
196196 else if ( ! topic . IsNew ) {
197- cache . GetOrAdd ( topic . Id , target ) ;
197+ cache . GetOrAdd (
198+ topic . Id ,
199+ new MappedTopicCacheEntry ( ) {
200+ MappedTopic = target ,
201+ Relationships = relationships
202+ }
203+ ) ;
198204 }
199205
200206 /*------------------------------------------------------------------------------------------------------------------------
@@ -227,12 +233,11 @@ private async Task<object> MapAsync(
227233 /// <param name="cache">A cache to keep track of already-mapped object instances.</param>
228234 /// <param name="attributePrefix">The prefix to apply to the attributes.</param>
229235 protected async Task SetPropertyAsync (
230- Topic source ,
231- object target ,
232- Relationships relationships ,
233- PropertyInfo property ,
234- ConcurrentDictionary < int , object > cache ,
235- string ? attributePrefix = null
236+ Topic source ,
237+ object target ,
238+ Relationships relationships ,
239+ PropertyInfo property ,
240+ MappedTopicCache cache ,
236241 ) {
237242
238243 /*------------------------------------------------------------------------------------------------------------------------
@@ -394,11 +399,11 @@ protected static void SetScalarValue(Topic source, object target, PropertyConfig
394399 /// </param>
395400 /// <param name="cache">A cache to keep track of already-mapped object instances.</param>
396401 protected async Task SetCollectionValueAsync (
397- Topic source ,
398- object target ,
399- Relationships relationships ,
400- PropertyConfiguration configuration ,
401- ConcurrentDictionary < int , object > cache
402+ Topic source ,
403+ object target ,
404+ Relationships relationships ,
405+ PropertyConfiguration configuration ,
406+ MappedTopicCache cache
402407 ) {
403408
404409 /*------------------------------------------------------------------------------------------------------------------------
@@ -586,10 +591,10 @@ IList<Topic> GetRelationship(RelationshipType relationship, Func<string, bool> c
586591 /// </param>
587592 /// <param name="cache">A cache to keep track of already-mapped object instances.</param>
588593 protected async Task PopulateTargetCollectionAsync (
589- IList < Topic > sourceList ,
590- IList targetList ,
591- PropertyConfiguration configuration ,
592- ConcurrentDictionary < int , object > cache
594+ IList < Topic > sourceList ,
595+ IList targetList ,
596+ PropertyConfiguration configuration ,
597+ MappedTopicCache cache
593598 ) {
594599
595600 /*------------------------------------------------------------------------------------------------------------------------
@@ -689,10 +694,10 @@ void AddToList(object dto) {
689694 /// </param>
690695 /// <param name="cache">A cache to keep track of already-mapped object instances.</param>
691696 protected async Task SetTopicReferenceAsync (
692- Topic source ,
693- object target ,
694- PropertyConfiguration configuration ,
695- ConcurrentDictionary < int , object > cache
697+ Topic source ,
698+ object target ,
699+ PropertyConfiguration configuration ,
700+ MappedTopicCache cache
696701 ) {
697702
698703 /*------------------------------------------------------------------------------------------------------------------------
0 commit comments