Skip to content

Commit 697b7e3

Browse files
committed
Removing unnecessary casting / Storing root mappers in a typed cache
1 parent 46565fa commit 697b7e3

File tree

5 files changed

+78
-29
lines changed

5 files changed

+78
-29
lines changed

AgileMapper/ObjectPopulation/ObjectMapper.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,9 @@ private ICache<ObjectMapperKeyBase, IObjectMapperFunc> CreateRecursionMapperFunc
8686

8787
public ObjectMapperData MapperData { get; }
8888

89-
public object Map(IObjectMappingData mappingData)
90-
{
91-
var typedData = (ObjectMappingData<TSource, TTarget>)mappingData;
89+
public object Map(IObjectMappingData mappingData) => Map((ObjectMappingData<TSource, TTarget>)mappingData);
9290

93-
return _mapperFunc.Invoke(typedData);
94-
}
91+
public TTarget Map(ObjectMappingData<TSource, TTarget> mappingData) => _mapperFunc.Invoke(mappingData);
9592

9693
public object MapChild<TDeclaredSource, TDeclaredTarget>(
9794
TDeclaredSource source,

AgileMapper/ObjectPopulation/ObjectMapperFactory.cs

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,42 @@
11
namespace AgileObjects.AgileMapper.ObjectPopulation
22
{
3+
using System.Collections.Generic;
34
using System.Linq.Expressions;
45
using Caching;
56

67
internal class ObjectMapperFactory
78
{
89
private readonly EnumerableMappingExpressionFactory _enumerableMappingExpressionFactory;
910
private readonly ComplexTypeMappingExpressionFactory _complexTypeMappingExpressionFactory;
10-
private readonly ICache<ObjectMapperKeyBase, IObjectMapper> _rootMappers;
11+
private readonly List<ICacheEmptier> _rootCacheEmptiers;
1112

1213
public ObjectMapperFactory(MapperContext mapperContext)
1314
{
1415
_enumerableMappingExpressionFactory = new EnumerableMappingExpressionFactory();
1516
_complexTypeMappingExpressionFactory = new ComplexTypeMappingExpressionFactory(mapperContext);
16-
_rootMappers = mapperContext.Cache.CreateScoped<ObjectMapperKeyBase, IObjectMapper>();
17+
_rootCacheEmptiers = new List<ICacheEmptier>();
1718
}
1819

19-
public IObjectMapper GetOrCreateRoot(IObjectMappingData mappingData) => _rootMappers.GetOrAddMapper(mappingData);
20+
public ObjectMapper<TSource, TTarget> GetOrCreateRoot<TSource, TTarget>(ObjectMappingData<TSource, TTarget> mappingData)
21+
{
22+
mappingData.MapperKey.MappingData = mappingData;
23+
24+
var mapper = RootMapperCache<TSource, TTarget>.Mappers.GetOrAdd(
25+
mappingData.MapperKey,
26+
key =>
27+
{
28+
var mapperToCache = (ObjectMapper<TSource, TTarget>)key.MappingData.Mapper;
29+
30+
key.MappingData = null;
31+
_rootCacheEmptiers.Add(CacheEmptier<TSource, TTarget>.Instance);
2032

21-
public IObjectMapper Create<TSource, TTarget>(IObjectMappingData mappingData)
33+
return mapperToCache;
34+
});
35+
36+
return mapper;
37+
}
38+
39+
public ObjectMapper<TSource, TTarget> Create<TSource, TTarget>(ObjectMappingData<TSource, TTarget> mappingData)
2240
{
2341
var mappingExpression = mappingData.MapperKey.MappingTypes.IsEnumerable
2442
? _enumerableMappingExpressionFactory.Create(mappingData)
@@ -38,8 +56,45 @@ public IObjectMapper Create<TSource, TTarget>(IObjectMappingData mappingData)
3856

3957
public void Reset()
4058
{
41-
_rootMappers.Empty();
4259
_complexTypeMappingExpressionFactory.Reset();
60+
61+
foreach (var rootCacheEmptier in _rootCacheEmptiers)
62+
{
63+
rootCacheEmptier.EmptyCache();
64+
}
65+
66+
_rootCacheEmptiers.Clear();
67+
}
68+
69+
#region Root Mapper Caching
70+
71+
private static class RootMapperCache<TSource, TTarget>
72+
{
73+
public static readonly ICache<ObjectMapperKeyBase, ObjectMapper<TSource, TTarget>> Mappers;
74+
75+
static RootMapperCache()
76+
{
77+
Mappers = GlobalContext.Instance
78+
.Cache
79+
.CreateScoped<ObjectMapperKeyBase, ObjectMapper<TSource, TTarget>>();
80+
}
81+
}
82+
83+
private interface ICacheEmptier
84+
{
85+
void EmptyCache();
4386
}
87+
88+
private class CacheEmptier<TSource, TTarget> : ICacheEmptier
89+
{
90+
public static readonly ICacheEmptier Instance = new CacheEmptier<TSource, TTarget>();
91+
92+
public void EmptyCache()
93+
{
94+
RootMapperCache<TSource, TTarget>.Mappers.Empty();
95+
}
96+
}
97+
98+
#endregion
4499
}
45100
}

AgileMapper/ObjectPopulation/ObjectMappingData.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ internal class ObjectMappingData<TSource, TTarget> :
1414
{
1515
private readonly IObjectMappingData _parent;
1616
private readonly Dictionary<object, List<object>> _mappedObjectsBySource;
17-
private IObjectMapper _mapper;
17+
private ObjectMapper<TSource, TTarget> _mapper;
1818
private ObjectMapperData _mapperData;
1919

2020
public ObjectMappingData(
@@ -62,7 +62,7 @@ private ObjectMappingData(
6262
return;
6363
}
6464

65-
Mapper = MapperContext.ObjectMapperFactory.GetOrCreateRoot(this);
65+
_mapper = MapperContext.ObjectMapperFactory.GetOrCreateRoot(this);
6666

6767
if (MapperData.MappedObjectCachingNeeded)
6868
{
@@ -76,16 +76,15 @@ private ObjectMappingData(
7676

7777
public ObjectMapperKeyBase MapperKey { get; }
7878

79-
public IObjectMapper Mapper
79+
IObjectMapper IObjectMappingData.Mapper
8080
{
81-
get { return _mapper ?? (Mapper = MapperContext.ObjectMapperFactory.Create<TSource, TTarget>(this)); }
82-
set
83-
{
84-
_mapper = value;
85-
_mapperData = _mapper.MapperData;
86-
}
81+
get { return Mapper; }
82+
set { _mapper = (ObjectMapper<TSource, TTarget>)value; }
8783
}
8884

85+
private ObjectMapper<TSource, TTarget> Mapper
86+
=> _mapper ?? (_mapper = MapperContext.ObjectMapperFactory.Create(this));
87+
8988
public TTarget CreatedObject { get; set; }
9089

9190
#region IObjectMappingData Members
@@ -101,7 +100,7 @@ public IObjectMapper Mapper
101100
public IObjectMappingData DeclaredTypeMappingData { get; }
102101

103102
public ObjectMapperData MapperData
104-
=> _mapperData ?? (_mapperData = ObjectMapperData.For<TSource, TTarget>(this));
103+
=> _mapperData ?? (_mapperData = _mapper?.MapperData ?? ObjectMapperData.For<TSource, TTarget>(this));
105104

106105
private ChildMemberMappingData<TSource, TTarget> _childMappingData;
107106

@@ -121,7 +120,7 @@ IMemberMappingData IObjectMappingData.GetChildMappingData(IMemberMapperData chil
121120

122121
#region Map Methods
123122

124-
public object MapStart() => Mapper.Map(this);
123+
public object MapStart() => _mapper.Map(this);
125124

126125
public TDeclaredTarget Map<TDeclaredSource, TDeclaredTarget>(
127126
TDeclaredSource sourceValue,

AgileMapper/ObjectPopulation/ObjectMappingDataFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ object IObjectMappingDataFactoryBridge.ForElement<TSource, TTarget>(object membe
171171
public static IObjectMappingData ForElement<TSource, TTarget>(
172172
TSource source,
173173
TTarget target,
174-
int? enumerableIndex,
174+
int enumerableIndex,
175175
IObjectMappingData parent)
176176
{
177177
var membersSource = new ElementMembersSource(parent);
@@ -187,7 +187,7 @@ public static IObjectMappingData ForElement<TSource, TTarget>(
187187
private static IObjectMappingData ForElement<TSource, TTarget>(
188188
TSource source,
189189
TTarget target,
190-
int? enumerableIndex,
190+
int enumerableIndex,
191191
IMembersSource membersSource,
192192
IObjectMappingData parent)
193193
{

AgileMapper/ObjectPopulation/RootObjectMapperKey.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,11 @@ public override bool Equals(object obj)
3232
{
3333
var otherKey = (RootObjectMapperKey)obj;
3434

35-
// ReSharper disable once PossibleNullReferenceException
36-
if ((otherKey._ruleSet == _ruleSet) && TypesMatch(otherKey))
37-
{
38-
return SourceHasRequiredTypes(otherKey);
39-
}
35+
// ObjectMapperFactory stores root mappers in a static, typed cache,
36+
// so MappingTypes checks are unnecessary
4037

41-
return false;
38+
// ReSharper disable once PossibleNullReferenceException
39+
return (otherKey._ruleSet == _ruleSet) && SourceHasRequiredTypes(otherKey);
4240
}
4341

4442
public override int GetHashCode() => 0;

0 commit comments

Comments
 (0)