Skip to content

Commit fac3579

Browse files
thomhurstclaude
andauthored
perf: Add caching to AttributeHelpers.GetCustomAttributesIncludingBaseInterfaces (#1730)
Fixes #1532 Add a ConcurrentDictionary cache to store attribute lookup results per (Type, AttributeType) combination to avoid repeated reflection calls on each invocation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7e132b5 commit fac3579

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,43 @@
1+
using System.Collections.Concurrent;
12
using System.Reflection;
23

34
namespace ModularPipelines.Extensions;
45

56
internal static class AttributeHelpers
67
{
8+
private static readonly ConcurrentDictionary<(Type Type, Type AttributeType), object[]> Cache = new();
9+
710
public static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>(this Type type)
811
where T : Attribute
912
{
13+
var key = (type, typeof(T));
14+
15+
if (Cache.TryGetValue(key, out var cachedResult))
16+
{
17+
return cachedResult.Cast<T>();
18+
}
19+
20+
var attributes = GetAttributesInternal<T>(type);
21+
Cache[key] = attributes;
22+
return attributes.Cast<T>();
23+
}
24+
25+
private static object[] GetAttributesInternal<T>(Type type)
26+
where T : Attribute
27+
{
28+
var results = new List<object>();
29+
1030
foreach (var result in type.GetInterfaces()
1131
.SelectMany(i => i.GetCustomAttributes<T>(true)))
1232
{
13-
yield return result;
33+
results.Add(result);
1434
}
1535

1636
foreach (var customAttribute in type.GetCustomAttributes<T>(true))
1737
{
18-
yield return customAttribute;
38+
results.Add(customAttribute);
1939
}
40+
41+
return results.ToArray();
2042
}
2143
}

0 commit comments

Comments
 (0)