-
-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
More dependency injection improvements (#208)
* Support IServiceProvider in builder pattern * Re-ordered parameters to match AddHttpClient format * Adds core support for named cache stacks * Hide previous implementations of builder pattern These won't be deprecated yet because they are so new but will be hidden by editors that observe the `EditorBrowsable` attribute. * Updated documentation * Use ServiceCollection implementation * Added initial tests for named cache stacks * Bringing ICacheContextActivator into the builder * Remove new ICacheContextActivator variations With the idea to move them to the builder pattern, there is no point adding new overloads that are already hidden. * Updated documentation * Use single NamedCacheStackLookup This technically allows a named `ICacheStack<TContext>` to be resolved from an `ICacheStackAccessor` as well as an `ICacheStackAccessor<TContext>`. For an `ICacheStack`, that will throw an exception if tried to be resolved from an `ICacheStackAccessor<TContext>`. * Fixed up test errors
- Loading branch information
Showing
4 changed files
with
362 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace CacheTower; | ||
|
||
/// <summary> | ||
/// Provides access to a named implementation of <see cref="ICacheStack"/>. | ||
/// </summary> | ||
public interface ICacheStackAccessor | ||
{ | ||
/// <summary> | ||
/// Creates or returns existing named <see cref="ICacheStack"/> base on the configured builder. | ||
/// </summary> | ||
/// <param name="name">The name of the <see cref="ICacheStack"/> that has been configured.</param> | ||
/// <returns></returns> | ||
ICacheStack GetCacheStack(string name); | ||
} | ||
|
||
/// <summary> | ||
/// Provides access to a named implementation of <see cref="ICacheStack{TContext}"/>. | ||
/// </summary> | ||
/// <typeparam name="TContext">The type of context that is passed during the cache entry generation process.</typeparam> | ||
public interface ICacheStackAccessor<TContext> | ||
{ | ||
/// <summary> | ||
/// Creates or returns existing named <see cref="ICacheStack{TContext}"/> base on the configured builder. | ||
/// </summary> | ||
/// <param name="name">The name of the <see cref="ICacheStack{TContext}"/> that has been configured.</param> | ||
/// <returns></returns> | ||
ICacheStack<TContext> GetCacheStack(string name); | ||
} | ||
|
||
internal record NamedCacheStackProvider(string Name, Func<IServiceProvider, ICacheStack> Provider); | ||
internal class NamedCacheStackLookup | ||
{ | ||
private readonly ConcurrentDictionary<string, Lazy<ICacheStack>> cachedDependencies = new(StringComparer.Ordinal); | ||
private readonly Dictionary<string, NamedCacheStackProvider> namedProviders; | ||
private readonly IServiceProvider serviceProvider; | ||
|
||
public NamedCacheStackLookup( | ||
IServiceProvider serviceProvider, | ||
IEnumerable<NamedCacheStackProvider> namedProviders | ||
) | ||
{ | ||
this.serviceProvider = serviceProvider; | ||
this.namedProviders = namedProviders.ToDictionary(p => p.Name); | ||
} | ||
|
||
public ICacheStack GetCacheStack(string name) | ||
{ | ||
if (!namedProviders.TryGetValue(name, out var dependencyProvider)) | ||
{ | ||
throw new ArgumentException($"No ICacheStack is registered with the name \"{name}\""); | ||
} | ||
|
||
return cachedDependencies.GetOrAdd(name, name => new Lazy<ICacheStack>(() => dependencyProvider.Provider(serviceProvider))).Value; | ||
} | ||
} | ||
|
||
internal class CacheStackAccessor : ICacheStackAccessor | ||
{ | ||
private readonly NamedCacheStackLookup cacheStackAccessor; | ||
|
||
public CacheStackAccessor(NamedCacheStackLookup cacheStackAccessor) | ||
{ | ||
this.cacheStackAccessor = cacheStackAccessor; | ||
} | ||
|
||
public ICacheStack GetCacheStack(string name) => cacheStackAccessor.GetCacheStack(name); | ||
} | ||
|
||
internal class CacheStackAccessor<TContext> : ICacheStackAccessor<TContext> | ||
{ | ||
private readonly NamedCacheStackLookup cacheStackAccessor; | ||
|
||
public CacheStackAccessor(NamedCacheStackLookup cacheStackAccessor) | ||
{ | ||
this.cacheStackAccessor = cacheStackAccessor; | ||
} | ||
|
||
public ICacheStack<TContext> GetCacheStack(string name) | ||
{ | ||
if (cacheStackAccessor.GetCacheStack(name) is not ICacheStack<TContext> cacheStack) | ||
{ | ||
throw new InvalidOperationException($"Registered ICacheStack for \"{name}\" is not compatible with {typeof(ICacheStack<TContext>)}"); | ||
} | ||
return cacheStack; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.