Skip to content
This repository was archived by the owner on Dec 13, 2021. It is now read-only.

Commit b993561

Browse files
authored
Merge pull request #241 from umco/patch/238-concurrency
AttributedTypeResolver - Adds locks to prevent concurrency issue
2 parents f35db30 + 597e20b commit b993561

File tree

2 files changed

+24
-13
lines changed

2 files changed

+24
-13
lines changed

src/Our.Umbraco.Ditto/ComponentModel/Attributes/DittoProcessorAttribute.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ protected DittoProcessorAttribute()
2121
{
2222
if (Ditto.TryGetTypeAttribute(this.GetType(), out DittoProcessorMetaDataAttribute metaData, true) == false || metaData == null)
2323
{
24-
throw new ApplicationException("Ditto processor attributes require a DittoProcessorMetaData attribute to be applied to the class but none was found.");
24+
throw new ApplicationException($"The Ditto processor attribute ('{this.GetType()}') requires a DittoProcessorMetaData attribute to be applied to the class but none was found.");
2525
}
2626

2727
this.ValueType = metaData.ValueType;

src/Our.Umbraco.Ditto/ComponentModel/ObjectResolution/AttributedTypeResolver.cs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,26 @@ namespace Our.Umbraco.Ditto
1212
/// <typeparam name="TAttribute">A specific Ditto attribute type.</typeparam>
1313
internal sealed class AttributedTypeResolver<TAttribute> where TAttribute : Attribute
1414
{
15-
private readonly ConcurrentDictionary<Type, TAttribute> _attributedTypeLookup;
15+
private readonly object _lock = new object();
16+
17+
private readonly Dictionary<Type, TAttribute> _attributedTypeLookup;
1618

1719
private AttributedTypeResolver()
1820
{
19-
_attributedTypeLookup = new ConcurrentDictionary<Type, TAttribute>();
21+
_attributedTypeLookup = new Dictionary<Type, TAttribute>();
2022
}
2123

2224
private void Initialize(IEnumerable<Type> types, bool inherit = false)
2325
{
24-
if (types != null)
26+
// NOTE: Lock when initializing the resolver, so that it can't be read from (at the same time).
27+
lock (_lock)
2528
{
26-
foreach (var type in types)
29+
if (types != null)
2730
{
28-
TryAddAttributedType(type, out TAttribute attribute, inherit);
31+
foreach (var type in types)
32+
{
33+
TryAddAttributedType(type, out TAttribute attribute, inherit);
34+
}
2935
}
3036
}
3137
}
@@ -83,7 +89,8 @@ private bool TryAddAttributedType(Type type, out TAttribute attribute, bool inhe
8389
{
8490
if (_attributedTypeLookup.ContainsKey(type) == false)
8591
{
86-
return _attributedTypeLookup.TryAdd(type, attribute);
92+
_attributedTypeLookup.Add(type, attribute);
93+
return true;
8794
}
8895
else
8996
{
@@ -103,14 +110,18 @@ private bool TryAddAttributedType(Type type, out TAttribute attribute, bool inhe
103110
/// <returns>Returns the associated attribute for the given object-type.</returns>
104111
public bool TryGetTypeAttribute(Type type, out TAttribute attribute, bool inherit = false)
105112
{
106-
bool result = _attributedTypeLookup.TryGetValue(type, out attribute);
107-
108-
if (result == false)
113+
// NOTE: Lock when looking up from the resolver, to avoid concurrency issues.
114+
lock (_lock)
109115
{
110-
result = TryAddAttributedType(type, out attribute, inherit);
111-
}
116+
bool result = _attributedTypeLookup.TryGetValue(type, out attribute);
112117

113-
return result;
118+
if (result == false)
119+
{
120+
result = TryAddAttributedType(type, out attribute, inherit);
121+
}
122+
123+
return result;
124+
}
114125
}
115126
}
116127
}

0 commit comments

Comments
 (0)