Skip to content

Commit 39ca0ab

Browse files
committed
Caching for adapted AnyKey registrations.
1 parent 9c1d1c3 commit 39ca0ab

3 files changed

Lines changed: 70 additions & 2 deletions

File tree

src/Autofac/Features/KeyedServices/AnyKeyRegistrationSource.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Autofac.Core.Activators.Delegate;
77
using Autofac.Core.Registration;
88
using Autofac.Util;
9+
using Autofac.Util.Cache;
910

1011
namespace Autofac.Features.KeyedServices;
1112

@@ -14,6 +15,17 @@ namespace Autofac.Features.KeyedServices;
1415
/// </summary>
1516
internal sealed class AnyKeyRegistrationSource : IRegistrationSource
1617
{
18+
private readonly ReflectionCacheKeyedServiceDictionary<IComponentRegistration[]> _adapterCache;
19+
20+
/// <summary>
21+
/// Initializes a new instance of the <see cref="AnyKeyRegistrationSource"/> class.
22+
/// </summary>
23+
public AnyKeyRegistrationSource()
24+
{
25+
_adapterCache = ReflectionCacheSet.Shared.GetOrCreateCache<ReflectionCacheKeyedServiceDictionary<IComponentRegistration[]>>(nameof(AnyKeyRegistrationSource));
26+
_adapterCache.Usage = ReflectionCacheUsage.Resolution;
27+
}
28+
1729
/// <inheritdoc/>
1830
public bool IsAdapterForIndividualComponents => true;
1931

@@ -37,6 +49,11 @@ public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Fun
3749
return Enumerable.Empty<IComponentRegistration>();
3850
}
3951

52+
if (_adapterCache.TryGetValue(keyedService, out var cached))
53+
{
54+
return cached;
55+
}
56+
4057
// If there are already specific registrations for this key, do nothing.
4158
if (registrationAccessor(service).Any())
4259
{
@@ -51,7 +68,14 @@ public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Fun
5168
return Enumerable.Empty<IComponentRegistration>();
5269
}
5370

54-
return anyKeyRegistrations.Select(r => CreateAdapterRegistration(r, keyedService));
71+
var adapters = new IComponentRegistration[anyKeyRegistrations.Length];
72+
for (var i = 0; i < anyKeyRegistrations.Length; i++)
73+
{
74+
adapters[i] = CreateAdapterRegistration(anyKeyRegistrations[i], keyedService);
75+
}
76+
77+
_adapterCache.TryAdd(keyedService, adapters);
78+
return adapters;
5579
}
5680

5781
private static ComponentRegistration CreateAdapterRegistration(ServiceRegistration anyKeyRegistration, KeyedService requestedService)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) Autofac Project. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using System.Collections.Concurrent;
5+
using System.Reflection;
6+
using Autofac.Core;
7+
8+
namespace Autofac.Util.Cache;
9+
10+
/// <summary>
11+
/// A reflection cache dictionary keyed on <see cref="KeyedService"/>, using the service type for cache eviction.
12+
/// </summary>
13+
/// <typeparam name="TValue">The value type.</typeparam>
14+
internal sealed class ReflectionCacheKeyedServiceDictionary<TValue>
15+
: ConcurrentDictionary<KeyedService, TValue>, IReflectionCache
16+
{
17+
/// <inheritdoc />
18+
public ReflectionCacheUsage Usage { get; set; } = ReflectionCacheUsage.All;
19+
20+
/// <inheritdoc />
21+
public void Clear(ReflectionCacheClearPredicate predicate)
22+
{
23+
if (predicate is null)
24+
{
25+
throw new ArgumentNullException(nameof(predicate));
26+
}
27+
28+
if (Count == 0)
29+
{
30+
return;
31+
}
32+
33+
var reusableAssemblySet = new HashSet<Assembly>();
34+
35+
foreach (var kvp in this)
36+
{
37+
var serviceType = kvp.Key.ServiceType;
38+
if (predicate(serviceType, TypeAssemblyReferenceProvider.GetAllReferencedAssemblies(serviceType, reusableAssemblySet)))
39+
{
40+
TryRemove(kvp.Key, out _);
41+
}
42+
}
43+
}
44+
}

src/Autofac/Util/Cache/ReflectionCacheParameterDictionary.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Autofac.Util.Cache;
1111
/// A reflection cache dictionary, keyed on a <see cref="ParameterInfo"/>.
1212
/// </summary>
1313
/// <typeparam name="TValue">The value type.</typeparam>
14-
public sealed class ReflectionCacheParameterDictionary<TValue>
14+
internal sealed class ReflectionCacheParameterDictionary<TValue>
1515
: ConcurrentDictionary<ParameterInfo, TValue>, IReflectionCache
1616
{
1717
/// <inheritdoc />

0 commit comments

Comments
 (0)