Skip to content

Commit 5a2b871

Browse files
authored
Merge pull request #14 from zms9110750/feature/pool-registration
Add policy factory overloads for pooled instance registration
2 parents a8982d9 + 4ffb101 commit 5a2b871

6 files changed

Lines changed: 570 additions & 14 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,6 @@ $RECYCLE.BIN/
166166

167167
# JetBrains Rider
168168
.idea
169+
170+
# Reasonix AI assistant
171+
.reasonix/

src/Autofac.Pooling/PoolActivator.cs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ namespace Autofac.Pooling;
1515
internal sealed class PoolActivator<TLimit> : IInstanceActivator
1616
where TLimit : class
1717
{
18-
private readonly Service _pooledInstanceService;
19-
private readonly IPooledRegistrationPolicy<TLimit> _policy;
20-
private readonly DefaultObjectPoolProvider _poolProvider;
18+
private readonly Service? _pooledInstanceService;
19+
private readonly IPooledRegistrationPolicy<TLimit>? _policy;
20+
private readonly DefaultObjectPoolProvider? _poolProvider;
21+
private readonly Func<IComponentContext, IPooledRegistrationPolicy<TLimit>>? _policyFactory;
2122

2223
/// <summary>
23-
/// Initializes a new instance of the <see cref="PoolActivator{TLimit}"/> class.
24+
/// Initializes a new instance of the <see cref="PoolActivator{TLimit}"/> class
25+
/// using the default <see cref="DefaultObjectPoolProvider"/>.
2426
/// </summary>
2527
/// <param name="pooledInstanceService">The service used to resolve new instances of the pooled registration.</param>
2628
/// <param name="policy">The pool policy.</param>
@@ -34,6 +36,23 @@ public PoolActivator(Service pooledInstanceService, IPooledRegistrationPolicy<TL
3436
};
3537
}
3638

39+
/// <summary>
40+
/// Initializes a new instance of the <see cref="PoolActivator{TLimit}"/> class
41+
/// using a factory function to create the <see cref="IPooledRegistrationPolicy{TLimit}"/> at resolve time.
42+
/// The default <see cref="DefaultObjectPoolProvider"/> will create the backing pool.
43+
/// </summary>
44+
/// <param name="pooledInstanceService">The service used to resolve new instances of the pooled registration.</param>
45+
/// <param name="policyFactory">
46+
/// A factory that returns the <see cref="IPooledRegistrationPolicy{TLimit}"/> to use.
47+
/// Invoked during resolve, so the <see cref="IComponentContext"/> is available
48+
/// for resolving dependencies.
49+
/// </param>
50+
public PoolActivator(Service pooledInstanceService, Func<IComponentContext, IPooledRegistrationPolicy<TLimit>> policyFactory)
51+
{
52+
_pooledInstanceService = pooledInstanceService;
53+
_policyFactory = policyFactory ?? throw new ArgumentNullException(nameof(policyFactory));
54+
}
55+
3756
/// <inheritdoc/>
3857
public Type LimitType { get; } = typeof(TLimit);
3958

@@ -42,15 +61,31 @@ public void ConfigurePipeline(IComponentRegistryServices componentRegistryServic
4261
{
4362
pipelineBuilder.Use(PipelinePhase.Activation, (context, next) =>
4463
{
45-
// Get a reference to the actual lifetime scope.
46-
var scope = context.Resolve<ILifetimeScope>();
64+
if (_policyFactory is not null)
65+
{
66+
// Custom policy factory: resolve the strategy at resolve time, then create DefaultObjectPool.
67+
var policy = _policyFactory(context);
68+
var poolProvider = new DefaultObjectPoolProvider
69+
{
70+
MaximumRetained = policy.MaximumRetained,
71+
};
72+
var scope = context.Resolve<ILifetimeScope>();
73+
var poolPolicy = new AutofacPooledObjectPolicy<TLimit>(_pooledInstanceService!, scope, policy);
74+
var pool = poolProvider.Create(poolPolicy);
75+
context.Instance = new PooledInstanceContext<TLimit>(pool, policy);
76+
}
77+
else
78+
{
79+
// Default path: use DefaultObjectPoolProvider + AutofacPooledObjectPolicy.
80+
var scope = context.Resolve<ILifetimeScope>();
4781

48-
var poolPolicy = new AutofacPooledObjectPolicy<TLimit>(_pooledInstanceService, scope, _policy);
82+
var poolPolicy = new AutofacPooledObjectPolicy<TLimit>(_pooledInstanceService!, scope, _policy!);
4983

50-
// The pool provider will create a disposable pool if the TLimit implements IDisposable.
51-
var pool = _poolProvider.Create(poolPolicy);
84+
// The pool provider will create a disposable pool if the TLimit implements IDisposable.
85+
var pool = _poolProvider!.Create(poolPolicy);
5286

53-
context.Instance = pool;
87+
context.Instance = pool;
88+
}
5489
});
5590
}
5691

src/Autofac.Pooling/PoolGetActivator.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal sealed class PoolGetActivator<TLimit> : IInstanceActivator
1717
where TLimit : class
1818
{
1919
private readonly PoolService _poolService;
20-
private readonly IPooledRegistrationPolicy<TLimit> _registrationPolicy;
20+
private readonly IPooledRegistrationPolicy<TLimit>? _registrationPolicy;
2121

2222
/// <summary>
2323
/// Initializes a new instance of the <see cref="PoolGetActivator{TLimit}"/> class.
@@ -30,6 +30,16 @@ public PoolGetActivator(PoolService poolService, IPooledRegistrationPolicy<TLimi
3030
_registrationPolicy = registrationPolicy;
3131
}
3232

33+
/// <summary>
34+
/// Initializes a new instance of the <see cref="PoolGetActivator{TLimit}"/> class.
35+
/// The policy will be retrieved from the <see cref="PooledInstanceContext{TLimit}"/> at resolve time.
36+
/// </summary>
37+
/// <param name="poolService">The service used to access the pool.</param>
38+
public PoolGetActivator(PoolService poolService)
39+
{
40+
_poolService = poolService;
41+
}
42+
3343
/// <inheritdoc/>
3444
public Type LimitType { get; } = typeof(TLimit);
3545

@@ -38,7 +48,10 @@ public void ConfigurePipeline(IComponentRegistryServices componentRegistryServic
3848
{
3949
pipelineBuilder.Use(PipelinePhase.Activation, (ctxt, next) =>
4050
{
41-
var pool = (ObjectPool<TLimit>)ctxt.ResolveService(_poolService);
51+
var resolved = ctxt.ResolveService(_poolService);
52+
var ctx = resolved as PooledInstanceContext<TLimit>;
53+
var pool = ctx is not null ? ctx.Pool : (ObjectPool<TLimit>)resolved;
54+
var policy = ctx is not null ? ctx.Policy : _registrationPolicy!;
4255
var didGetFromPool = false;
4356

4457
TLimit PoolGet()
@@ -47,11 +60,11 @@ TLimit PoolGet()
4760
return pool.Get();
4861
}
4962

50-
var poolItem = _registrationPolicy.Get(ctxt, ctxt.Parameters, PoolGet) ?? throw new InvalidOperationException(
63+
var poolItem = policy.Get(ctxt, ctxt.Parameters, PoolGet) ?? throw new InvalidOperationException(
5164
string.Format(
5265
CultureInfo.CurrentCulture,
5366
PoolGetActivatorResources.PolicyMustReturnInstance,
54-
_registrationPolicy.GetType().FullName,
67+
policy.GetType().FullName,
5568
typeof(TLimit).FullName));
5669

5770
if (didGetFromPool)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 Microsoft.Extensions.ObjectPool;
5+
6+
namespace Autofac.Pooling;
7+
8+
/// <summary>
9+
/// Holds a resolved pool and its associated policy instance,
10+
/// so the policy created during pool construction is shared with the get-side activator.
11+
/// </summary>
12+
/// <typeparam name="TLimit">The limit type of the objects in the pool.</typeparam>
13+
internal sealed class PooledInstanceContext<TLimit>
14+
where TLimit : class
15+
{
16+
/// <summary>
17+
/// Initializes a new instance of the <see cref="PooledInstanceContext{TLimit}"/> class.
18+
/// </summary>
19+
/// <param name="pool">The object pool.</param>
20+
/// <param name="policy">The resolved registration policy.</param>
21+
public PooledInstanceContext(ObjectPool<TLimit> pool, IPooledRegistrationPolicy<TLimit> policy)
22+
{
23+
Pool = pool;
24+
Policy = policy;
25+
}
26+
27+
/// <summary>
28+
/// Gets the object pool.
29+
/// </summary>
30+
public ObjectPool<TLimit> Pool
31+
{
32+
get;
33+
}
34+
35+
/// <summary>
36+
/// Gets the resolved registration policy, shared between pool creation and retrieval.
37+
/// </summary>
38+
public IPooledRegistrationPolicy<TLimit> Policy
39+
{
40+
get;
41+
}
42+
}

0 commit comments

Comments
 (0)