@@ -20,8 +20,8 @@ public static class Reflection
2020 private const bool ShouldInheritAttributes = false ;
2121
2222 private static readonly ConcurrentDictionary < Type , ConstructorInfo > TypesWithOneConstructorCache = new ConcurrentDictionary < Type , ConstructorInfo > ( ) ;
23- private static readonly ConcurrentDictionary < Type , object > TypeAttributesCache = new ConcurrentDictionary < Type , object > ( ) ;
24- private static readonly ConcurrentDictionary < Type , object > MethodAttributesCache = new ConcurrentDictionary < Type , object > ( ) ;
23+ private static readonly ConcurrentDictionary < Type , IEnumerable < object > > TypeAttributesCache = new ConcurrentDictionary < Type , IEnumerable < object > > ( ) ;
24+ private static readonly ConcurrentDictionary < MethodInfo , IEnumerable < object > > MethodAttributesCache = new ConcurrentDictionary < MethodInfo , IEnumerable < object > > ( ) ;
2525 private static readonly ConcurrentDictionary < Type , string > FriendlyTypeNames = new ConcurrentDictionary < Type , string > ( ) ;
2626 private static readonly ConcurrentDictionary < Type , string > FullFriendlyTypeNames = new ConcurrentDictionary < Type , string > ( ) ;
2727
@@ -291,19 +291,10 @@ public static IEnumerable<object> GetCustomAttributes(object obj, bool shouldInh
291291 {
292292 var type = obj . GetType ( ) ;
293293 var attributes = type . GetTypeInfo ( ) . GetCustomAttributes ( shouldInherit ) ;
294+ UpdateAttributesIfNeeded ( type , attributes , TypeAttributesCache ) ;
294295
295- if ( ! HasAnyAttributes ( attributes , TypeAttributesCache ) )
296- {
297- return attributes ;
298- }
299-
300- if ( attributes . Length == TypeAttributesCache . Count )
301- {
302- return TypeAttributesCache . Values ;
303- }
304-
305- CacheAttributes ( attributes , TypeAttributesCache ) ;
306- return TypeAttributesCache . Values ;
296+ return TypeAttributesCache
297+ . GetOrAdd ( type , _ => attributes ) ;
307298 }
308299
309300 /// <summary>
@@ -315,19 +306,10 @@ public static IEnumerable<object> GetCustomAttributes(object obj, bool shouldInh
315306 public static IEnumerable < object > GetCustomAttributes ( MethodInfo method , bool shouldInherit = ShouldInheritAttributes )
316307 {
317308 var attributes = method . GetCustomAttributes ( shouldInherit ) ;
309+ UpdateAttributesIfNeeded ( method , attributes , MethodAttributesCache ) ;
318310
319- if ( ! HasAnyAttributes ( attributes , MethodAttributesCache ) )
320- {
321- return attributes ;
322- }
323-
324- if ( attributes . Length == MethodAttributesCache . Count )
325- {
326- return MethodAttributesCache . Values ;
327- }
328-
329- CacheAttributes ( attributes , MethodAttributesCache ) ;
330- return MethodAttributesCache . Values ;
311+ return MethodAttributesCache
312+ . GetOrAdd ( method , _ => attributes ) ;
331313 }
332314
333315 /// <summary>
@@ -757,21 +739,17 @@ private static bool ObjectPropertiesAreDeeplyEqual(
757739 return result . Success ;
758740 }
759741
760- private static void CacheAttributes ( IEnumerable < object > attributes , ConcurrentDictionary < Type , object > result )
742+ private static void UpdateAttributesIfNeeded < T > (
743+ T key ,
744+ object [ ] attributes ,
745+ ConcurrentDictionary < T , IEnumerable < object > > result )
761746 {
762- foreach ( var attribute in attributes )
747+ if ( result . ContainsKey ( key ) )
763748 {
764- var attributeType = attribute . GetType ( ) ;
765- if ( ! result . ContainsKey ( attributeType ) )
766- {
767- result . TryAdd ( attributeType , attribute ) ;
768- }
749+ result . AddOrUpdate ( key , attributes , ( dictKey , oldValue ) => attributes ) ;
769750 }
770751 }
771752
772- private static bool HasAnyAttributes ( IReadOnlyCollection < object > attributes , ConcurrentDictionary < Type , object > result )
773- => attributes . Count != 0 || result . Any ( ) ;
774-
775753 private static string GetFriendlyTypeName ( Type type , bool useFullName )
776754 {
777755 const string anonymousTypePrefix = "<>f__" ;
0 commit comments