Skip to content

Commit 205400a

Browse files
committed
Merge pull request #10 from Tasteful/Threadsafe
Threadsafe - ConcurrentDictionary instead of IDictionary
2 parents 5c24d4e + 5d4db5c commit 205400a

8 files changed

Lines changed: 51 additions & 91 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,4 @@ ModelManifest.xml
190190
*.dll
191191
src/AutoMapper.Collection/packages/AutoMapper.3.3.1/lib/wpa81/AutoMapper.xml
192192
src/AutoMapper.Collection/packages/
193+
/src/AutoMapper.Collection/AutoMapper.Collection.sln.GhostDoc.xml

src/AutoMapper.Collection/AutoMapper.Collection/AutoMapper.Collection.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
<Compile Include="Equivilency Expression\UserDefinedEquivilentExpressions.cs" />
6363
</ItemGroup>
6464
<ItemGroup>
65-
<None Include="Equivilency Expression\packages.config" />
6665
<None Include="packages.config">
6766
<SubType>Designer</SubType>
6867
</None>
Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Linq;
45
using System.Linq.Expressions;
@@ -7,34 +8,28 @@ namespace AutoMapper.EquivilencyExpression
78
{
89
public static class ExpressionExtentions
910
{
10-
private static readonly IDictionary<Type, Type> _singleParameterTypeDictionary = new Dictionary<Type, Type>();
11+
private static readonly ConcurrentDictionary<Type, Type> _singleParameterTypeDictionary = new ConcurrentDictionary<Type, Type>();
1112

1213
public static Type GetSinglePredicateExpressionArgumentType(this Type type)
1314
{
14-
if (_singleParameterTypeDictionary.ContainsKey(type))
15-
return _singleParameterTypeDictionary[type];
15+
return _singleParameterTypeDictionary.GetOrAdd(type, t =>
16+
{
17+
var isExpression = typeof(Expression).IsAssignableFrom(t);
18+
if (!isExpression)
19+
return null;
1620

17-
var isExpression = typeof(Expression).IsAssignableFrom(type);
18-
if (!isExpression)
19-
return CacheAndReturnType(type, null);
21+
var expressionOf = t.GetGenericArguments().First();
22+
var isFunction = expressionOf.GetGenericTypeDefinition() == typeof(Func<,>);
23+
if (!isFunction)
24+
return null;
2025

21-
var expressionOf = type.GetGenericArguments().First();
22-
var isFunction = expressionOf.GetGenericTypeDefinition() == typeof(Func<,>);
23-
if (!isFunction)
24-
return CacheAndReturnType(type, null);
26+
var isPredicate = expressionOf.GetGenericArguments()[1] == typeof(bool);
27+
if (!isPredicate)
28+
return null;
2529

26-
var isPredicate = expressionOf.GetGenericArguments()[1] == typeof(bool);
27-
if (!isPredicate)
28-
return CacheAndReturnType(type, null);
29-
30-
var objType = expressionOf.GetGenericArguments().First();
31-
return CacheAndReturnType(type, objType);
32-
}
33-
34-
private static Type CacheAndReturnType(Type type, Type objType)
35-
{
36-
_singleParameterTypeDictionary.Add(type, objType);
37-
return objType;
30+
var objType = expressionOf.GetGenericArguments().First();
31+
return objType;
32+
});
3833
}
3934
}
4035
}

src/AutoMapper.Collection/AutoMapper.Collection/Equivilency Expression/GenerateEquivilentExpressionFromTypeMap.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1+
using System.Collections.Concurrent;
12
using System.Collections.Generic;
23
using System.Linq.Expressions;
34

45
namespace AutoMapper.EquivilencyExpression
56
{
67
internal class GenerateEquivilentExpressionFromTypeMap
78
{
8-
private static readonly IDictionary<TypeMap, GenerateEquivilentExpressionFromTypeMap> _equivilentExpressionses = new Dictionary<TypeMap, GenerateEquivilentExpressionFromTypeMap>();
9+
private static readonly ConcurrentDictionary<TypeMap, GenerateEquivilentExpressionFromTypeMap> _equivilentExpressionses = new ConcurrentDictionary<TypeMap, GenerateEquivilentExpressionFromTypeMap>();
910
internal static Expression GetExpression(TypeMap typeMap, object value)
1011
{
11-
if (!_equivilentExpressionses.ContainsKey(typeMap))
12-
_equivilentExpressionses.Add(typeMap, new GenerateEquivilentExpressionFromTypeMap(typeMap));
13-
return _equivilentExpressionses[typeMap].CreateEquivilentExpression(value);
12+
return _equivilentExpressionses.GetOrAdd(typeMap, t => new GenerateEquivilentExpressionFromTypeMap(t))
13+
.CreateEquivilentExpression(value);
1414
}
1515

1616
private readonly TypeMap _typeMap;
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Linq;
45

@@ -7,7 +8,7 @@ namespace AutoMapper.EquivilencyExpression
78
public abstract class GenerateEquivilentExpressionsBasedOnGeneratePropertyMaps : IGenerateEquivilentExpressions
89
{
910
private readonly IGeneratePropertyMaps _generatePropertyMaps;
10-
readonly IDictionary<Type, IDictionary<Type, IGenerateEquivilentExpressions>> _sourceToDestPropMaps = new Dictionary<Type, IDictionary<Type, IGenerateEquivilentExpressions>>();
11+
readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, IGenerateEquivilentExpressions>> _sourceToDestPropMaps = new ConcurrentDictionary<Type, ConcurrentDictionary<Type, IGenerateEquivilentExpressions>>();
1112

1213
protected GenerateEquivilentExpressionsBasedOnGeneratePropertyMaps(IGeneratePropertyMaps generatePropertyMaps)
1314
{
@@ -16,7 +17,6 @@ protected GenerateEquivilentExpressionsBasedOnGeneratePropertyMaps(IGenerateProp
1617

1718
public bool CanGenerateEquivilentExpression(Type sourceType, Type destinationType)
1819
{
19-
UpdateIfExpressionDoesNotExist(sourceType, destinationType);
2020
return GetPropertyMatches(sourceType, destinationType) != GenerateEquivilentExpressions.BadValue;
2121
}
2222

@@ -27,37 +27,20 @@ public IEquivilentExpression GeneratEquivilentExpression(Type sourceType, Type d
2727

2828
private IGenerateEquivilentExpressions GetPropertyMatches(Type sourceType, Type destinationType)
2929
{
30-
return _sourceToDestPropMaps[sourceType][destinationType];
31-
}
32-
33-
private void UpdateIfExpressionDoesNotExist(Type sourceType, Type destinationType)
34-
{
35-
UpdateDictionaryHolder(sourceType, destinationType);
36-
var properyMappings = _sourceToDestPropMaps[sourceType][destinationType];
37-
38-
if (properyMappings != null)
39-
return;
40-
41-
try
42-
{
43-
var keyProperties = _generatePropertyMaps.GeneratePropertyMaps(sourceType, destinationType);
44-
if (!keyProperties.Any())
45-
_sourceToDestPropMaps[sourceType][destinationType] = GenerateEquivilentExpressions.BadValue;
46-
else
47-
_sourceToDestPropMaps[sourceType][destinationType] = new GenerateEquivilentExpressionOnPropertyMaps(keyProperties);
48-
}
49-
catch (Exception ex)
50-
{
51-
_sourceToDestPropMaps[sourceType][destinationType] = GenerateEquivilentExpressions.BadValue;
52-
}
53-
}
54-
55-
private void UpdateDictionaryHolder(Type sourceType, Type destinationType)
56-
{
57-
if (!_sourceToDestPropMaps.ContainsKey(sourceType))
58-
_sourceToDestPropMaps.Add(sourceType, new Dictionary<Type, IGenerateEquivilentExpressions>());
59-
if (!_sourceToDestPropMaps[sourceType].ContainsKey(destinationType))
60-
_sourceToDestPropMaps[sourceType].Add(destinationType, null);
30+
return _sourceToDestPropMaps
31+
.GetOrAdd(sourceType, t => new ConcurrentDictionary<Type, IGenerateEquivilentExpressions>())
32+
.GetOrAdd(destinationType, t =>
33+
{
34+
try
35+
{
36+
var keyProperties = _generatePropertyMaps.GeneratePropertyMaps(sourceType, destinationType);
37+
return keyProperties.Any() ? new GenerateEquivilentExpressionOnPropertyMaps(keyProperties) : GenerateEquivilentExpressions.BadValue;
38+
}
39+
catch (Exception ex)
40+
{
41+
return GenerateEquivilentExpressions.BadValue;
42+
}
43+
});
6144
}
6245
}
6346
}
Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Linq.Expressions;
45

56
namespace AutoMapper.EquivilencyExpression
67
{
78
internal class UserDefinedEquivilentExpressions : IGenerateEquivilentExpressions
89
{
9-
private readonly IDictionary<Type, IDictionary<Type, IEquivilentExpression>> _equivilentExpressionDictionary = new Dictionary<Type, IDictionary<Type, IEquivilentExpression>>();
10+
private readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, IEquivilentExpression>> _equivilentExpressionDictionary = new ConcurrentDictionary<Type, ConcurrentDictionary<Type, IEquivilentExpression>>();
1011

1112
public bool CanGenerateEquivilentExpression(Type sourceType, Type destinationType)
1213
{
@@ -20,37 +21,21 @@ public IEquivilentExpression GeneratEquivilentExpression(Type sourceType, Type d
2021

2122
private IEquivilentExpression GetEquivlelentExpression(Type srcType, Type destType)
2223
{
23-
if (_equivilentExpressionDictionary.ContainsKey(destType))
24-
if (_equivilentExpressionDictionary[destType].ContainsKey(srcType))
25-
return _equivilentExpressionDictionary[destType][srcType];
24+
ConcurrentDictionary<Type, IEquivilentExpression> destMap;
25+
IEquivilentExpression srcExpression;
26+
if (_equivilentExpressionDictionary.TryGetValue(destType, out destMap) && destMap.TryGetValue(srcType, out srcExpression))
27+
{
28+
return srcExpression;
29+
}
2630
return null;
2731
}
2832

2933
internal void AddEquivilencyExpression<TSource, TDestination>(Expression<Func<TSource, TDestination, bool>> equivilentExpression)
3034
where TSource : class
3135
where TDestination : class
3236
{
33-
var destinationDictionary = GetOrGenerateDefinitionDictionary<TDestination>();
34-
SetEquivlientExpressionForSource<TSource>(destinationDictionary, new EquivilentExpression<TSource, TDestination>(equivilentExpression));
35-
}
36-
37-
private void SetEquivlientExpressionForSource<TSource>(IDictionary<Type, IEquivilentExpression> destinationDictionary, IEquivilentExpression equivilentExpression)
38-
{
39-
GetOrGenerateSourceDictionary<TSource>(destinationDictionary);
40-
destinationDictionary[typeof(TSource)] = equivilentExpression;
41-
}
42-
43-
private IDictionary<Type, IEquivilentExpression> GetOrGenerateDefinitionDictionary<TDestination>()
44-
{
45-
if (!_equivilentExpressionDictionary.ContainsKey(typeof(TDestination)))
46-
_equivilentExpressionDictionary.Add(typeof(TDestination), new Dictionary<Type, IEquivilentExpression>());
47-
return _equivilentExpressionDictionary[typeof(TDestination)];
48-
}
49-
50-
private void GetOrGenerateSourceDictionary<TSource>(IDictionary<Type, IEquivilentExpression> destinationDictionary)
51-
{
52-
if (!destinationDictionary.ContainsKey(typeof(TSource)))
53-
destinationDictionary.Add(typeof(TSource), null);
37+
var destinationDictionary = _equivilentExpressionDictionary.GetOrAdd(typeof(TDestination), t => new ConcurrentDictionary<Type, IEquivilentExpression>());
38+
destinationDictionary.AddOrUpdate(typeof(TSource), new EquivilentExpression<TSource, TDestination>(equivilentExpression), (type, old) => new EquivilentExpression<TSource, TDestination>(equivilentExpression));
5439
}
5540
}
5641
}

src/AutoMapper.Collection/AutoMapper.Collection/Equivilency Expression/packages.config

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/AutoMapper.Collection/AutoMapper.Collection/Properties/AssemblyInfo.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("1.1.2.0")]
36-
[assembly: AssemblyFileVersion("1.1.2.0")]
35+
[assembly: AssemblyVersion("1.1.3")]
36+
[assembly: AssemblyFileVersion("1.1.3")]
37+
[assembly: AssemblyInformationalVersion("1.1.3")]

0 commit comments

Comments
 (0)