Skip to content

Commit 32a8b7b

Browse files
Updated the AddPolicyRegistry extension methods to use TryAdd and TryAddEnumerable internally (#47821)
* Added TryAddPolicyRegistry extension methods for IPolicyRegistry * Added missing using statement * Undone changes on PublicAPI.Shipped.txt * Added the TryAddPolicyRegistry extension methods to the PublicAPI.Unshipped.txt * Updated the AddPolicyRegistry extension methods to use TryAdd and TryAddEnumerable internally * Trigger again build pipeline * Updated the AddPolicyRegistry extension methods to fix failing unit tests * Updated the AddPolicyRegistry extension methods and added unit tests * Revert global.json changes * Revert global.json changes to latest version * Revert global.json changes to latest version * Fixed unit tests * Added missing using statement in unit tests * Updated only the parameterless AddPolicyRegistry overload to an add-if-missing operation * Cleanup. Added missing space --------- Co-authored-by: Iustin Micu <[email protected]>
1 parent 392a090 commit 32a8b7b

File tree

2 files changed

+76
-8
lines changed

2 files changed

+76
-8
lines changed

src/HttpClientFactory/Polly/src/DependencyInjection/PollyServiceCollectionExtensions.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using Polly.Registry;
6+
using Microsoft.Extensions.DependencyInjection.Extensions;
67

78
namespace Microsoft.Extensions.DependencyInjection;
89

@@ -15,24 +16,33 @@ public static class PollyServiceCollectionExtensions
1516
/// <summary>
1617
/// Registers an empty <see cref="PolicyRegistry"/> in the service collection with service types
1718
/// <see cref="IPolicyRegistry{String}"/>, <see cref="IReadOnlyPolicyRegistry{String}"/>, and
18-
/// <see cref="IConcurrentPolicyRegistry{String}"/> and returns the newly created registry.
19+
/// <see cref="IConcurrentPolicyRegistry{String}"/> if the service types haven't already been registered
20+
/// and returns the existing or newly created registry.
1921
/// </summary>
2022
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
21-
/// <returns>The newly created <see cref="IPolicyRegistry{String}"/>.</returns>
23+
/// <returns>The existing or newly created <see cref="IPolicyRegistry{String}"/>.</returns>
2224
public static IPolicyRegistry<string> AddPolicyRegistry(this IServiceCollection services)
2325
{
2426
if (services == null)
2527
{
2628
throw new ArgumentNullException(nameof(services));
2729
}
2830

29-
// Create an empty registry, register and return it as an instance. This is the best way to get a
30-
// single instance registered using all the interfaces.
31-
var registry = new PolicyRegistry();
31+
// Get existing registry or an empty instance
32+
var registry = services.BuildServiceProvider().GetService<IPolicyRegistry<string>>();
33+
if (registry == null)
34+
{
35+
registry = new PolicyRegistry();
36+
}
3237

33-
services.AddSingleton<IConcurrentPolicyRegistry<string>>(registry);
34-
services.AddSingleton<IPolicyRegistry<string>>(registry);
35-
services.AddSingleton<IReadOnlyPolicyRegistry<string>>(registry);
38+
// Try to register for the missing interfaces
39+
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPolicyRegistry<string>>(registry));
40+
services.TryAddEnumerable(ServiceDescriptor.Singleton<IReadOnlyPolicyRegistry<string>>(registry));
41+
42+
if (registry is IConcurrentPolicyRegistry<string> concurrentRegistry)
43+
{
44+
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConcurrentPolicyRegistry<string>>(concurrentRegistry));
45+
}
3646

3747
return registry;
3848
}

src/HttpClientFactory/Polly/test/DependencyInjection/PollyHttpClientBuilderExtensionsTest.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Net;
78
using System.Net.Http;
89
using System.Threading;
@@ -522,6 +523,63 @@ public void AddPolicyHandlerFromRegistry_WithConfigureDelegate_AddsPolicyRegistr
522523
Assert.Same(registry, services.GetService<IReadOnlyPolicyRegistry<string>>());
523524
}
524525

526+
[Fact]
527+
public void AddPolicyRegistry_DoesNotOverrideOrAddExtraRegistrations()
528+
{
529+
// Arrange
530+
var serviceCollection = new ServiceCollection();
531+
532+
// Act 1
533+
var existingRegistry = serviceCollection.AddPolicyRegistry();
534+
535+
// Act 2
536+
var registry = serviceCollection.AddPolicyRegistry();
537+
var services = serviceCollection.BuildServiceProvider();
538+
539+
// Assert
540+
Assert.NotNull(existingRegistry);
541+
Assert.Same(existingRegistry, registry);
542+
543+
Assert.Same(existingRegistry, services.GetService<IPolicyRegistry<string>>());
544+
Assert.Same(existingRegistry, services.GetService<IConcurrentPolicyRegistry<string>>());
545+
Assert.Same(existingRegistry, services.GetService<IReadOnlyPolicyRegistry<string>>());
546+
547+
Assert.Single(serviceCollection, sd => sd.ServiceType == typeof(IPolicyRegistry<string>));
548+
Assert.Single(serviceCollection, sd => sd.ServiceType == typeof(IReadOnlyPolicyRegistry<string>));
549+
Assert.Single(serviceCollection, sd => sd.ServiceType == typeof(IConcurrentPolicyRegistry<string>));
550+
}
551+
552+
[Theory]
553+
[InlineData(typeof(IPolicyRegistry<string>))]
554+
[InlineData(typeof(IReadOnlyPolicyRegistry<string>))]
555+
[InlineData(typeof(IConcurrentPolicyRegistry<string>))]
556+
public void AddPolicyRegistry_AddsOnlyMissingRegistrations(Type missingType)
557+
{
558+
// Arrange
559+
var serviceCollection = new ServiceCollection();
560+
var registry = new PolicyRegistry();
561+
var policyTypes = new List<Type>
562+
{
563+
typeof(IPolicyRegistry<string>),
564+
typeof(IReadOnlyPolicyRegistry<string>),
565+
typeof(IConcurrentPolicyRegistry<string>)
566+
};
567+
568+
// Act 1
569+
foreach (var policyType in policyTypes.Where(x => x != missingType))
570+
{
571+
serviceCollection.AddSingleton(policyType, registry);
572+
}
573+
574+
// Act 2
575+
serviceCollection.AddPolicyRegistry();
576+
577+
// Assert
578+
Assert.Single(serviceCollection, sd => sd.ServiceType == typeof(IPolicyRegistry<string>));
579+
Assert.Single(serviceCollection, sd => sd.ServiceType == typeof(IReadOnlyPolicyRegistry<string>));
580+
Assert.Single(serviceCollection, sd => sd.ServiceType == typeof(IConcurrentPolicyRegistry<string>));
581+
}
582+
525583
// Throws an exception or fails on even numbered requests, otherwise succeeds.
526584
private class FaultyMessageHandler : DelegatingHandler
527585
{

0 commit comments

Comments
 (0)