diff --git a/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs b/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs index 52458f8b1422fb..130a170c3b30ed 100644 --- a/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs +++ b/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs @@ -126,6 +126,7 @@ public partial struct RateLimitPartition private int _dummyPrimitive; public RateLimitPartition(TKey partitionKey, System.Func factory) { throw null; } public readonly TKey PartitionKey { get { throw null; } } + public readonly Func Factory { get { throw null; } } } public abstract partial class ReplenishingRateLimiter : System.Threading.RateLimiting.RateLimiter { diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/RateLimitPartition.T.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/RateLimitPartition.T.cs index bbec73cc98c617..ac51ff5a9e7547 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/RateLimitPartition.T.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/RateLimitPartition.T.cs @@ -25,6 +25,9 @@ public RateLimitPartition(TKey partitionKey, Func factory) /// public TKey PartitionKey { get; } - internal readonly Func Factory; + /// + /// The function called when a rate limiter for the given partitionKey is needed. + /// + public Func Factory { get; } } } diff --git a/src/libraries/System.Threading.RateLimiting/tests/RateLimiterPartitionTests.cs b/src/libraries/System.Threading.RateLimiting/tests/RateLimiterPartitionTests.cs index 175c4e96fdcda1..04b715da07ebb2 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/RateLimiterPartitionTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/RateLimiterPartitionTests.cs @@ -14,9 +14,7 @@ public void Create_Concurrency() var options = new ConcurrencyLimiterOptions(10, QueueProcessingOrder.OldestFirst, 10); var partition = RateLimitPartition.CreateConcurrencyLimiter(1, key => options); - var factoryProperty = typeof(RateLimitPartition).GetField("Factory", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; - var factory = (Func)factoryProperty.GetValue(partition); - var limiter = factory(1); + var limiter = partition.Factory(1); var concurrencyLimiter = Assert.IsType(limiter); Assert.Equal(options.PermitLimit, concurrencyLimiter.GetAvailablePermits()); } @@ -27,9 +25,7 @@ public void Create_TokenBucket() var options = new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 10, TimeSpan.FromMinutes(1), 1, true); var partition = RateLimitPartition.CreateTokenBucketLimiter(1, key => options); - var factoryProperty = typeof(RateLimitPartition).GetField("Factory", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; - var factory = (Func)factoryProperty.GetValue(partition); - var limiter = factory(1); + var limiter = partition.Factory(1); var tokenBucketLimiter = Assert.IsType(limiter); Assert.Equal(options.TokenLimit, tokenBucketLimiter.GetAvailablePermits()); Assert.Equal(options.ReplenishmentPeriod, tokenBucketLimiter.ReplenishmentPeriod); @@ -41,9 +37,7 @@ public async Task Create_NoLimiter() { var partition = RateLimitPartition.CreateNoLimiter(1); - var factoryProperty = typeof(RateLimitPartition).GetField("Factory", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; - var factory = (Func)factoryProperty.GetValue(partition); - var limiter = factory(1); + var limiter = partition.Factory(1); // How do we test an internal implementation of a limiter that doesn't limit? Just try some stuff that normal limiters would probably block on and see if it works. var available = limiter.GetAvailablePermits(); @@ -67,15 +61,12 @@ public void Create_AnyLimiter() { var partition = RateLimitPartition.Create(1, key => new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 10))); - var factoryProperty = typeof(RateLimitPartition).GetField("Factory", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; - var factory = (Func)factoryProperty.GetValue(partition); - var limiter = factory(1); + var limiter = partition.Factory(1); var concurrencyLimiter = Assert.IsType(limiter); Assert.Equal(1, concurrencyLimiter.GetAvailablePermits()); var partition2 = RateLimitPartition.Create(1, key => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 10, TimeSpan.FromMilliseconds(100), 1, autoReplenishment: false))); - factory = (Func)factoryProperty.GetValue(partition2); - limiter = factory(1); + limiter = partition2.Factory(1); var tokenBucketLimiter = Assert.IsType(limiter); Assert.Equal(1, tokenBucketLimiter.GetAvailablePermits()); } @@ -86,9 +77,7 @@ public void Create_FixedWindow() var options = new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 10, TimeSpan.FromMinutes(1), true); var partition = RateLimitPartition.CreateFixedWindowLimiter(1, key => options); - var factoryProperty = typeof(RateLimitPartition).GetField("Factory", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; - var factory = (Func)factoryProperty.GetValue(partition); - var limiter = factory(1); + var limiter = partition.Factory(1); var fixedWindowLimiter = Assert.IsType(limiter); Assert.Equal(options.PermitLimit, fixedWindowLimiter.GetAvailablePermits()); Assert.Equal(options.Window, fixedWindowLimiter.ReplenishmentPeriod); @@ -101,9 +90,7 @@ public void Create_SlidingWindow() var options = new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 10, TimeSpan.FromSeconds(33), 3, true); var partition = RateLimitPartition.CreateSlidingWindowLimiter(1, key => options); - var factoryProperty = typeof(RateLimitPartition).GetField("Factory", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance)!; - var factory = (Func)factoryProperty.GetValue(partition); - var limiter = factory(1); + var limiter = partition.Factory(1); var slidingWindowLimiter = Assert.IsType(limiter); Assert.Equal(options.PermitLimit, slidingWindowLimiter.GetAvailablePermits()); Assert.Equal(TimeSpan.FromSeconds(11), slidingWindowLimiter.ReplenishmentPeriod);