11using Microsoft . Extensions . DependencyInjection ;
22using Microsoft . Extensions . Caching . Memory ;
33using Microsoft . Extensions . Logging ;
4+ using Microsoft . Extensions . Options ;
45
56using Reliable . HttpClient . Caching . Abstractions ;
67
@@ -19,39 +20,41 @@ public static class HttpClientWithCacheExtensions
1920 /// <param name="cacheOptions">Cache options including default headers and settings (optional)</param>
2021 /// <returns>Service collection for method chaining</returns>
2122 public static IServiceCollection AddHttpClientWithCache (
22- this IServiceCollection services ,
23- string ? httpClientName = null ,
24- HttpCacheOptions ? cacheOptions = null )
23+ this IServiceCollection services ,
24+ string ? httpClientName = null ,
25+ HttpCacheOptions ? cacheOptions = null )
2526 {
2627 // Register dependencies
2728 services . AddMemoryCache ( ) ;
2829 services . AddSingleton < ISimpleCacheKeyGenerator , DefaultSimpleCacheKeyGenerator > ( ) ;
2930
30- // Register the universal HTTP client with cache
31- services . AddSingleton < IHttpClientWithCache > ( serviceProvider =>
32- {
33- IHttpClientFactory httpClientFactory = serviceProvider . GetRequiredService < IHttpClientFactory > ( ) ;
34- System . Net . Http . HttpClient httpClient = httpClientName is null or ""
35- ? httpClientFactory . CreateClient ( )
36- : httpClientFactory . CreateClient ( httpClientName ) ;
37-
38- IMemoryCache cache = serviceProvider . GetRequiredService < IMemoryCache > ( ) ;
39- IHttpResponseHandler responseHandler = serviceProvider . GetRequiredService < IHttpResponseHandler > ( ) ; // Use universal handler
40- ISimpleCacheKeyGenerator cacheKeyGenerator = serviceProvider . GetRequiredService < ISimpleCacheKeyGenerator > ( ) ;
41- ILogger < HttpClientWithCache > ? logger = serviceProvider . GetService < ILogger < HttpClientWithCache > > ( ) ;
42-
43- return new HttpClientWithCache (
44- httpClient ,
45- cache ,
46- responseHandler ,
47- cacheOptions ,
48- cacheKeyGenerator ,
49- logger ) ;
50- } ) ;
31+ // Register the universal HTTP client with cache as scoped to avoid captive dependency
32+ services . AddScoped < IHttpClientWithCache > ( sp => CreateHttpClientWithCache ( sp , httpClientName , cacheOptions ) ) ;
33+ services . AddScoped ( sp => ( HttpClientWithCache ) sp . GetRequiredService < IHttpClientWithCache > ( ) ) ;
5134
5235 return services ;
5336 }
5437
38+ /// <summary>
39+ /// Adds universal HTTP client with caching to the service collection
40+ /// </summary>
41+ /// <param name="services">Service collection</param>
42+ /// <param name="httpClientName">HTTP client name (optional)</param>
43+ /// <param name="configureCacheOptions">Action to configure cache options
44+ /// which then will be registered as <see cref="IOptions{TOptions}"/> named after <paramref name="httpClientName"/></param>
45+ /// <returns>Service collection for method chaining</returns>
46+ public static IServiceCollection AddHttpClientWithCache (
47+ this IServiceCollection services ,
48+ string ? httpClientName ,
49+ Action < HttpCacheOptions > configureCacheOptions )
50+ {
51+ var options = new HttpCacheOptions ( ) ;
52+ configureCacheOptions ( options ) ;
53+ services . Configure ( httpClientName , configureCacheOptions ) ;
54+
55+ return services . AddHttpClientWithCache ( httpClientName , options ) ;
56+ }
57+
5558 /// <summary>
5659 /// Adds universal HTTP client with caching and resilience to the service collection
5760 /// </summary>
@@ -97,4 +100,86 @@ public static IServiceCollection AddResilientHttpClientWithCache(
97100 // Add universal HTTP client with cache
98101 return services . AddHttpClientWithCache ( httpClientName , cacheOptions ) ;
99102 }
103+
104+ /// <summary>
105+ /// Adds universal HTTP client with caching and resilience to the service collection
106+ /// </summary>
107+ /// <param name="services">Service collection</param>
108+ /// <param name="httpClientName">HTTP client name</param>
109+ /// <param name="configureResilience">Action to configure resilience options</param>
110+ /// <param name="configureCacheOptions">Action to configure cache options</param>
111+ /// <returns>Service collection for method chaining</returns>
112+ public static IServiceCollection AddResilientHttpClientWithCache (
113+ this IServiceCollection services ,
114+ string httpClientName ,
115+ Action < HttpCacheOptions > configureCacheOptions ,
116+ Action < HttpClientOptions > ? configureResilience = null )
117+ {
118+ var cacheOptions = new HttpCacheOptions ( ) ;
119+ configureCacheOptions ( cacheOptions ) ;
120+ services . Configure ( httpClientName , configureCacheOptions ) ;
121+
122+ return services . AddResilientHttpClientWithCache ( httpClientName , configureResilience , cacheOptions ) ;
123+ }
124+
125+ /// <summary>
126+ /// Adds universal HTTP client with caching using preset resilience configuration
127+ /// </summary>
128+ /// <param name="services">Service collection</param>
129+ /// <param name="httpClientName">HTTP client name</param>
130+ /// <param name="preset">Predefined resilience preset</param>
131+ /// <param name="customizeOptions">Optional action to customize preset options</param>
132+ /// <param name="configureCacheOptions">Action to configure cache options</param>
133+ /// <returns>Service collection for method chaining</returns>
134+ public static IServiceCollection AddResilientHttpClientWithCache (
135+ this IServiceCollection services ,
136+ string httpClientName ,
137+ HttpClientOptions preset ,
138+ Action < HttpCacheOptions > configureCacheOptions ,
139+ Action < HttpClientOptions > ? customizeOptions = null )
140+ {
141+ var cacheOptions = new HttpCacheOptions ( ) ;
142+ configureCacheOptions ( cacheOptions ) ;
143+ services . Configure ( httpClientName , configureCacheOptions ) ;
144+
145+ return services . AddResilientHttpClientWithCache ( httpClientName , preset , customizeOptions , cacheOptions ) ;
146+ }
147+
148+ /// <summary>
149+ /// Creates an instance of <see cref="HttpClientWithCache"/> using the provided service provider and configuration.
150+ /// </summary>
151+ /// <param name="serviceProvider">The service provider used to resolve required dependencies.</param>
152+ /// <param name="httpClientName">The name of the HTTP client to retrieve from the <see cref="IHttpClientFactory"/>.
153+ /// <param name="cacheOptions">Cache options including default headers and settings (optional)</param>
154+ /// If null or empty, a default client is created.</param>
155+ /// <returns>A configured instance of <see cref="HttpClientWithCache"/>.</returns>
156+ /// <exception cref="InvalidOperationException">Thrown if a required service (e.g., <see cref="IHttpClientFactory"/>, <see cref="IMemoryCache"/>,
157+ /// <see cref="IHttpResponseHandler"/>, or <see cref="ISimpleCacheKeyGenerator"/>) is not registered in the service provider.</exception>
158+ private static HttpClientWithCache CreateHttpClientWithCache (
159+ IServiceProvider serviceProvider ,
160+ string ? httpClientName ,
161+ HttpCacheOptions ? cacheOptions )
162+ {
163+ IHttpClientFactory httpClientFactory = serviceProvider . GetRequiredService < IHttpClientFactory > ( ) ;
164+ System . Net . Http . HttpClient httpClient = httpClientName is null or ""
165+ ? httpClientFactory . CreateClient ( )
166+ : httpClientFactory . CreateClient ( httpClientName ) ;
167+
168+ IMemoryCache cache = serviceProvider . GetRequiredService < IMemoryCache > ( ) ;
169+ IHttpResponseHandler responseHandler = serviceProvider . GetRequiredService < IHttpResponseHandler > ( ) ;
170+ HttpCacheOptions ? cacheOptionsToInject = cacheOptions is null
171+ ? serviceProvider . GetService < IOptionsSnapshot < HttpCacheOptions > > ( ) ? . Get ( httpClientName )
172+ : cacheOptions ;
173+ IOptionsSnapshot < HttpCacheOptions > ? cacheOptionsSnapshot = serviceProvider . GetService < IOptionsSnapshot < HttpCacheOptions > > ( ) ;
174+ ISimpleCacheKeyGenerator cacheKeyGenerator = serviceProvider . GetRequiredService < ISimpleCacheKeyGenerator > ( ) ;
175+ ILogger < HttpClientWithCache > ? logger = serviceProvider . GetService < ILogger < HttpClientWithCache > > ( ) ;
176+
177+ return new HttpClientWithCache (
178+ httpClient ,
179+ cache ,
180+ responseHandler ,
181+ cacheOptionsToInject ,
182+ cacheKeyGenerator ,
183+ logger ) ;
184+ }
100185}
0 commit comments