Fix UmbracoMapper InvalidOperationException due to concurrent modification of inner dictionary (#15830)
This commit is contained in:
committed by
Sebastiaan Janssen
parent
2fbda6e64b
commit
4a977b85a2
@@ -43,8 +43,8 @@ public class UmbracoMapper : IUmbracoMapper
|
||||
// note
|
||||
//
|
||||
// the outer dictionary *can* be modified, see GetCtor and GetMap, hence have to be ConcurrentDictionary
|
||||
// the inner dictionaries are never modified and therefore can be simple Dictionary
|
||||
private readonly ConcurrentDictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>> _ctors =
|
||||
// the inner dictionaries can also be modified, see GetCtor and therefore also needs to be a ConcurrentDictionary
|
||||
private readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, Func<object, MapperContext, object>>> _ctors =
|
||||
new();
|
||||
|
||||
private readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, Action<object, object, MapperContext>>> _maps =
|
||||
@@ -129,7 +129,7 @@ public class UmbracoMapper : IUmbracoMapper
|
||||
Type sourceType = typeof(TSource);
|
||||
Type targetType = typeof(TTarget);
|
||||
|
||||
Dictionary<Type, Func<object, MapperContext, object>> sourceCtors = DefineCtors(sourceType);
|
||||
ConcurrentDictionary<Type, Func<object, MapperContext, object>> sourceCtors = DefineCtors(sourceType);
|
||||
if (ctor != null)
|
||||
{
|
||||
sourceCtors[targetType] = (source, context) => ctor((TSource)source, context)!;
|
||||
@@ -139,8 +139,8 @@ public class UmbracoMapper : IUmbracoMapper
|
||||
sourceMaps[targetType] = (source, target, context) => map((TSource)source, (TTarget)target, context);
|
||||
}
|
||||
|
||||
private Dictionary<Type, Func<object, MapperContext, object>> DefineCtors(Type sourceType) =>
|
||||
_ctors.GetOrAdd(sourceType, _ => new Dictionary<Type, Func<object, MapperContext, object>>());
|
||||
private ConcurrentDictionary<Type, Func<object, MapperContext, object>> DefineCtors(Type sourceType) =>
|
||||
_ctors.GetOrAdd(sourceType, _ => new ConcurrentDictionary<Type, Func<object, MapperContext, object>>());
|
||||
|
||||
private ConcurrentDictionary<Type, Action<object, object, MapperContext>> DefineMaps(Type sourceType) =>
|
||||
_maps.GetOrAdd(sourceType, _ => new ConcurrentDictionary<Type, Action<object, object, MapperContext>>());
|
||||
@@ -391,7 +391,7 @@ public class UmbracoMapper : IUmbracoMapper
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_ctors.TryGetValue(sourceType, out Dictionary<Type, Func<object, MapperContext, object>>? sourceCtor) &&
|
||||
if (_ctors.TryGetValue(sourceType, out ConcurrentDictionary<Type, Func<object, MapperContext, object>>? sourceCtor) &&
|
||||
sourceCtor.TryGetValue(targetType, out Func<object, MapperContext, object>? ctor))
|
||||
{
|
||||
return ctor;
|
||||
@@ -399,7 +399,7 @@ public class UmbracoMapper : IUmbracoMapper
|
||||
|
||||
// we *may* run this more than once but it does not matter
|
||||
ctor = null;
|
||||
foreach ((Type stype, Dictionary<Type, Func<object, MapperContext, object>> sctors) in _ctors)
|
||||
foreach ((Type stype, ConcurrentDictionary<Type, Func<object, MapperContext, object>> sctors) in _ctors)
|
||||
{
|
||||
if (!stype.IsAssignableFrom(sourceType))
|
||||
{
|
||||
@@ -427,7 +427,7 @@ public class UmbracoMapper : IUmbracoMapper
|
||||
{
|
||||
if (!v.ContainsKey(c.Key))
|
||||
{
|
||||
v.Add(c.Key, c.Value);
|
||||
v.TryAdd(c.Key, c.Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user