diff --git a/src/Our.Umbraco.Ditto/ComponentModel/Attributes/DittoProcessorAttribute.cs b/src/Our.Umbraco.Ditto/ComponentModel/Attributes/DittoProcessorAttribute.cs index 17a6c44..9754926 100644 --- a/src/Our.Umbraco.Ditto/ComponentModel/Attributes/DittoProcessorAttribute.cs +++ b/src/Our.Umbraco.Ditto/ComponentModel/Attributes/DittoProcessorAttribute.cs @@ -21,7 +21,7 @@ protected DittoProcessorAttribute() { if (Ditto.TryGetTypeAttribute(this.GetType(), out DittoProcessorMetaDataAttribute metaData, true) == false || metaData == null) { - throw new ApplicationException("Ditto processor attributes require a DittoProcessorMetaData attribute to be applied to the class but none was found."); + throw new ApplicationException($"The Ditto processor attribute ('{this.GetType()}') requires a DittoProcessorMetaData attribute to be applied to the class but none was found."); } this.ValueType = metaData.ValueType; diff --git a/src/Our.Umbraco.Ditto/ComponentModel/ObjectResolution/AttributedTypeResolver.cs b/src/Our.Umbraco.Ditto/ComponentModel/ObjectResolution/AttributedTypeResolver.cs index 6dab172..b5c5814 100644 --- a/src/Our.Umbraco.Ditto/ComponentModel/ObjectResolution/AttributedTypeResolver.cs +++ b/src/Our.Umbraco.Ditto/ComponentModel/ObjectResolution/AttributedTypeResolver.cs @@ -12,20 +12,26 @@ namespace Our.Umbraco.Ditto /// A specific Ditto attribute type. internal sealed class AttributedTypeResolver where TAttribute : Attribute { - private readonly ConcurrentDictionary _attributedTypeLookup; + private readonly object _lock = new object(); + + private readonly Dictionary _attributedTypeLookup; private AttributedTypeResolver() { - _attributedTypeLookup = new ConcurrentDictionary(); + _attributedTypeLookup = new Dictionary(); } private void Initialize(IEnumerable types, bool inherit = false) { - if (types != null) + // NOTE: Lock when initializing the resolver, so that it can't be read from (at the same time). + lock (_lock) { - foreach (var type in types) + if (types != null) { - TryAddAttributedType(type, out TAttribute attribute, inherit); + foreach (var type in types) + { + TryAddAttributedType(type, out TAttribute attribute, inherit); + } } } } @@ -83,7 +89,8 @@ private bool TryAddAttributedType(Type type, out TAttribute attribute, bool inhe { if (_attributedTypeLookup.ContainsKey(type) == false) { - return _attributedTypeLookup.TryAdd(type, attribute); + _attributedTypeLookup.Add(type, attribute); + return true; } else { @@ -103,14 +110,18 @@ private bool TryAddAttributedType(Type type, out TAttribute attribute, bool inhe /// Returns the associated attribute for the given object-type. public bool TryGetTypeAttribute(Type type, out TAttribute attribute, bool inherit = false) { - bool result = _attributedTypeLookup.TryGetValue(type, out attribute); - - if (result == false) + // NOTE: Lock when looking up from the resolver, to avoid concurrency issues. + lock (_lock) { - result = TryAddAttributedType(type, out attribute, inherit); - } + bool result = _attributedTypeLookup.TryGetValue(type, out attribute); - return result; + if (result == false) + { + result = TryAddAttributedType(type, out attribute, inherit); + } + + return result; + } } } } \ No newline at end of file