Skip to content

Commit 4f911fc

Browse files
committed
Moving static mapper caching into a dedicated class
1 parent ec57f72 commit 4f911fc

File tree

3 files changed

+114
-166
lines changed

3 files changed

+114
-166
lines changed

AgileMapper/ObjectPopulation/ObjectMapperFactory.cs

Lines changed: 2 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ namespace AgileObjects.AgileMapper.ObjectPopulation
88
using Enumerables;
99
using Extensions.Internal;
1010
using Queryables;
11-
using Validation;
1211

1312
internal class ObjectMapperFactory
1413
{
@@ -45,77 +44,16 @@ public void RegisterCreationCallback(MapperCreationCallbackKey creationCallbackK
4544

4645
public ObjectMapper<TSource, TTarget> GetOrCreateRoot<TSource, TTarget>(ObjectMappingData<TSource, TTarget> mappingData)
4746
{
48-
if (TryGetStaticallyCachedMapper(mappingData, out var mapper))
47+
if (StaticMapperCache<TSource, TTarget>.TryGetMapperFor(mappingData, out var mapper))
4948
{
5049
return mapper;
5150
}
5251

53-
// TODO: This is not thread-safe when using a fixed-types RootObjectMapperKey!
5452
mappingData.MapperKey.MappingData = mappingData;
5553

5654
mapper = (ObjectMapper<TSource, TTarget>)_rootMappersCache.GetOrAdd(
5755
mappingData.MapperKey,
58-
key =>
59-
{
60-
var mapperToCache = key.MappingData.GetOrCreateMapper();
61-
var data = key.MappingData;
62-
63-
key.MappingData = null;
64-
65-
if (mapperToCache.MapperData.MapperContext.UserConfigurations.ValidateMappingPlans)
66-
{
67-
MappingValidator.Validate(mapperToCache.MapperData);
68-
}
69-
70-
if (mapperToCache.IsStaticallyCacheable(key))
71-
{
72-
var ruleSets = data.MapperData.MapperContext.RuleSets;
73-
74-
if (data.MappingContext.RuleSet == ruleSets.CreateNew)
75-
{
76-
if (StaticCreateNewMapperCache<TSource, TTarget>.Mapper != null)
77-
{
78-
goto SkipStaticCaching;
79-
}
80-
81-
return StaticCreateNewMapperCache<TSource, TTarget>.SetMapper((ObjectMapper<TSource, TTarget>)mapperToCache);
82-
}
83-
84-
if (data.MappingContext.RuleSet == ruleSets.Overwrite)
85-
{
86-
if (StaticOverwriteMapperCache<TSource, TTarget>.Mapper != null)
87-
{
88-
goto SkipStaticCaching;
89-
}
90-
91-
return StaticOverwriteMapperCache<TSource, TTarget>.SetMapper((ObjectMapper<TSource, TTarget>)mapperToCache);
92-
}
93-
94-
if (data.MappingContext.RuleSet == ruleSets.Project)
95-
{
96-
if (StaticProjectionMapperCache<TSource, TTarget>.Mapper != null)
97-
{
98-
goto SkipStaticCaching;
99-
}
100-
101-
return StaticProjectionMapperCache<TSource, TTarget>.SetMapper((ObjectMapper<TSource, TTarget>)mapperToCache);
102-
}
103-
104-
if (data.MappingContext.RuleSet == ruleSets.Merge)
105-
{
106-
if (StaticMergeMapperCache<TSource, TTarget>.Mapper != null)
107-
{
108-
goto SkipStaticCaching;
109-
}
110-
111-
return StaticMergeMapperCache<TSource, TTarget>.SetMapper((ObjectMapper<TSource, TTarget>)mapperToCache);
112-
}
113-
}
114-
115-
SkipStaticCaching:
116-
117-
return mapperToCache;
118-
});
56+
key => key.MappingData.GetOrCreateMapper());
11957

12058
return mapper;
12159
}
@@ -154,107 +92,6 @@ public ObjectMapper<TSource, TTarget> Create<TSource, TTarget>(ObjectMappingData
15492
return mapper;
15593
}
15694

157-
#region Static Caches
158-
159-
private static bool TryGetStaticallyCachedMapper<TSource, TTarget>(
160-
ObjectMappingData<TSource, TTarget> mappingData,
161-
out ObjectMapper<TSource, TTarget> mapper)
162-
{
163-
var ruleSet = mappingData.MappingContext.RuleSet;
164-
var ruleSets = mappingData.MapperContext.RuleSets;
165-
166-
if (ruleSet == ruleSets.CreateNew)
167-
{
168-
if (StaticCreateNewMapperCache<TSource, TTarget>.Mapper?.MapperData.MapperContext != mappingData.MapperContext)
169-
{
170-
goto NoCachedMapper;
171-
}
172-
173-
mapper = StaticCreateNewMapperCache<TSource, TTarget>.Mapper;
174-
return true;
175-
}
176-
177-
if (ruleSet == ruleSets.Overwrite)
178-
{
179-
if (StaticOverwriteMapperCache<TSource, TTarget>.Mapper?.MapperData.MapperContext != mappingData.MapperContext)
180-
{
181-
goto NoCachedMapper;
182-
}
183-
184-
mapper = StaticOverwriteMapperCache<TSource, TTarget>.Mapper;
185-
return true;
186-
}
187-
188-
if (ruleSet == ruleSets.Project)
189-
{
190-
if (StaticProjectionMapperCache<TSource, TTarget>.Mapper?.MapperData.MapperContext != mappingData.MapperContext)
191-
{
192-
goto NoCachedMapper;
193-
}
194-
195-
mapper = StaticProjectionMapperCache<TSource, TTarget>.Mapper;
196-
return true;
197-
}
198-
199-
if (ruleSet == ruleSets.Merge)
200-
{
201-
if (StaticMergeMapperCache<TSource, TTarget>.Mapper?.MapperData.MapperContext != mappingData.MapperContext)
202-
{
203-
goto NoCachedMapper;
204-
}
205-
206-
mapper = StaticMergeMapperCache<TSource, TTarget>.Mapper;
207-
return true;
208-
}
209-
210-
NoCachedMapper:
211-
212-
mapper = null;
213-
return false;
214-
}
215-
216-
private static class StaticCreateNewMapperCache<TSource, TTarget>
217-
{
218-
public static ObjectMapper<TSource, TTarget> Mapper { get; private set; }
219-
220-
public static ObjectMapper<TSource, TTarget> SetMapper(ObjectMapper<TSource, TTarget> mapper)
221-
=> Mapper = mapper.WithResetCallback(Reset);
222-
223-
private static void Reset() => Mapper = null;
224-
}
225-
226-
private static class StaticOverwriteMapperCache<TSource, TTarget>
227-
{
228-
public static ObjectMapper<TSource, TTarget> Mapper { get; private set; }
229-
230-
public static ObjectMapper<TSource, TTarget> SetMapper(ObjectMapper<TSource, TTarget> mapper)
231-
=> Mapper = mapper.WithResetCallback(Reset);
232-
233-
private static void Reset() => Mapper = null;
234-
}
235-
236-
private static class StaticProjectionMapperCache<TSource, TTarget>
237-
{
238-
public static ObjectMapper<TSource, TTarget> Mapper { get; private set; }
239-
240-
public static ObjectMapper<TSource, TTarget> SetMapper(ObjectMapper<TSource, TTarget> mapper)
241-
=> Mapper = mapper.WithResetCallback(Reset);
242-
243-
private static void Reset() => Mapper = null;
244-
}
245-
246-
private static class StaticMergeMapperCache<TSource, TTarget>
247-
{
248-
public static ObjectMapper<TSource, TTarget> Mapper { get; private set; }
249-
250-
public static ObjectMapper<TSource, TTarget> SetMapper(ObjectMapper<TSource, TTarget> mapper)
251-
=> Mapper = mapper.WithResetCallback(Reset);
252-
253-
private static void Reset() => Mapper = null;
254-
}
255-
256-
#endregion
257-
25895
public void Reset()
25996
{
26097
foreach (var mappingExpressionFactory in _mappingExpressionFactories)

AgileMapper/ObjectPopulation/ObjectMappingData.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace AgileObjects.AgileMapper.ObjectPopulation
55
using System.Linq.Expressions;
66
using Extensions.Internal;
77
using Members;
8+
using Validation;
89

910
internal class ObjectMappingData<TSource, TTarget> :
1011
MappingInstanceData<TSource, TTarget>,
@@ -69,7 +70,26 @@ private ObjectMappingData(
6970
public ObjectMapperKeyBase MapperKey { get; }
7071

7172
public IObjectMapper GetOrCreateMapper()
72-
=> _mapper ?? (_mapper = MapperContext.ObjectMapperFactory.Create(this));
73+
{
74+
if (_mapper != null)
75+
{
76+
return _mapper;
77+
}
78+
79+
_mapper = MapperContext.ObjectMapperFactory.Create(this);
80+
81+
MapperKey.MappingData = null;
82+
83+
if (MapperContext.UserConfigurations.ValidateMappingPlans)
84+
{
85+
// TODO: Test coverage for validation of standalone child mappers
86+
MappingValidator.Validate(_mapper.MapperData);
87+
}
88+
89+
StaticMapperCache<TSource, TTarget>.AddIfAppropriate(_mapper, this);
90+
91+
return _mapper;
92+
}
7393

7494
public void SetMapper(IObjectMapper mapper)
7595
=> _mapper = (ObjectMapper<TSource, TTarget>)mapper;
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
namespace AgileObjects.AgileMapper.ObjectPopulation
2+
{
3+
internal static class StaticMapperCache<TSource, TTarget>
4+
{
5+
private static readonly MapperCache _createNew = new MapperCache();
6+
private static readonly MapperCache _overwrite = new MapperCache();
7+
private static readonly MapperCache _project = new MapperCache();
8+
private static readonly MapperCache _merge = new MapperCache();
9+
10+
public static void AddIfAppropriate(ObjectMapper<TSource, TTarget> mapper, IObjectMappingData mappingData)
11+
{
12+
if (!mappingData.IsRoot ||
13+
mappingData.IsPartOfDerivedTypeMapping ||
14+
!mapper.IsStaticallyCacheable(mappingData.MapperKey))
15+
{
16+
return;
17+
}
18+
19+
var ruleSets = mappingData.MappingContext.MapperContext.RuleSets;
20+
21+
if (mappingData.MappingContext.RuleSet == ruleSets.CreateNew)
22+
{
23+
_createNew.SetMapperIfAppropriate(mapper);
24+
return;
25+
}
26+
27+
if (mappingData.MappingContext.RuleSet == ruleSets.Overwrite)
28+
{
29+
_overwrite.SetMapperIfAppropriate(mapper);
30+
return;
31+
}
32+
33+
if (mappingData.MappingContext.RuleSet == ruleSets.Project)
34+
{
35+
_project.SetMapperIfAppropriate(mapper);
36+
return;
37+
}
38+
39+
_merge.SetMapperIfAppropriate(mapper);
40+
}
41+
42+
public static bool TryGetMapperFor(IObjectMappingData mappingData, out ObjectMapper<TSource, TTarget> mapper)
43+
{
44+
var ruleSets = mappingData.MappingContext.MapperContext.RuleSets;
45+
46+
if (mappingData.MappingContext.RuleSet == ruleSets.CreateNew)
47+
{
48+
return _createNew.TryGetMapper(mappingData, out mapper);
49+
}
50+
51+
if (mappingData.MappingContext.RuleSet == ruleSets.Overwrite)
52+
{
53+
return _overwrite.TryGetMapper(mappingData, out mapper);
54+
}
55+
56+
if (mappingData.MappingContext.RuleSet == ruleSets.Project)
57+
{
58+
return _project.TryGetMapper(mappingData, out mapper);
59+
}
60+
61+
return _merge.TryGetMapper(mappingData, out mapper);
62+
}
63+
64+
private class MapperCache
65+
{
66+
private ObjectMapper<TSource, TTarget> _mapper;
67+
68+
public void SetMapperIfAppropriate(ObjectMapper<TSource, TTarget> mapper)
69+
{
70+
if (_mapper == null)
71+
{
72+
_mapper = mapper.WithResetCallback(Reset);
73+
}
74+
}
75+
76+
public bool TryGetMapper(IObjectMappingData key, out ObjectMapper<TSource, TTarget> mapper)
77+
{
78+
if (_mapper?.MapperData.MapperContext != key.MappingContext.MapperContext)
79+
{
80+
mapper = null;
81+
return false;
82+
}
83+
84+
mapper = _mapper;
85+
return true;
86+
}
87+
88+
private void Reset() => _mapper = null;
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)