Skip to content

Commit 5d48792

Browse files
feat: required outer services for agent accessor chain (#40)
* feat: required outer services for agent accessor chain this feature allows access to required services from the service provider that constructed the agent accessor chain * refactor: appease codacy gods also move the method which builds a service provider to a private static method, keep ctor tidy
1 parent f4f55b8 commit 5d48792

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

src/EntityDb.Common/Agents/AgentAccessorChain.cs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,52 @@ public class AgentAccessorChain : IAgentAccessor
2121
private readonly IAgentAccessor[] _agentAccessors;
2222

2323
/// <ignore/>
24-
public AgentAccessorChain(ILogger<AgentAccessorChain> logger, IOptions<AgentAccessorChainOptions> options) : this(logger, options.Value)
24+
public AgentAccessorChain
25+
(
26+
ILogger<AgentAccessorChain> logger,
27+
IOptions<AgentAccessorChainOptions> options,
28+
IServiceProvider outerServiceProvider
29+
) : this(logger, options.Value, outerServiceProvider)
2530
{
2631
}
2732

28-
internal AgentAccessorChain(ILogger<AgentAccessorChain> logger, AgentAccessorChainOptions options)
33+
internal AgentAccessorChain
34+
(
35+
ILogger<AgentAccessorChain> logger,
36+
AgentAccessorChainOptions options,
37+
IServiceProvider outerServiceProvider
38+
)
2939
{
30-
var serviceProvider = options.ServiceCollection
31-
.BuildServiceProvider();
40+
var serviceProvider = GetServiceProvider(outerServiceProvider, options);
3241

3342
_logger = logger;
3443
_agentAccessors = serviceProvider
3544
.GetServices<IAgentAccessor>()
3645
.ToArray();
3746
}
3847

48+
private static IServiceProvider GetServiceProvider(IServiceProvider outerServiceProvider, AgentAccessorChainOptions options)
49+
{
50+
IServiceCollection serviceCollectionCopy = new ServiceCollection();
51+
52+
foreach (var (outerServiceType, innerServiceLifetime) in options.RequiredOuterServices)
53+
{
54+
serviceCollectionCopy.Add(new ServiceDescriptor
55+
(
56+
outerServiceType,
57+
_ => outerServiceProvider.GetRequiredService(outerServiceType),
58+
innerServiceLifetime
59+
));
60+
}
61+
62+
foreach (var serviceDescriptor in options.ServiceCollection)
63+
{
64+
serviceCollectionCopy.Add(serviceDescriptor);
65+
}
66+
67+
return serviceCollectionCopy.BuildServiceProvider();
68+
}
69+
3970
/// <inheritdoc />
4071
public IAgent GetAgent()
4172
{

src/EntityDb.Common/Agents/AgentAccessorChainOptions.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using EntityDb.Abstractions.Agents;
22
using Microsoft.Extensions.DependencyInjection;
3+
using System;
4+
using System.Collections.Generic;
35

46
namespace EntityDb.Common.Agents;
57

@@ -9,7 +11,19 @@ namespace EntityDb.Common.Agents;
911
public sealed class AgentAccessorChainOptions
1012
{
1113
/// <summary>
12-
/// A service collection used to resolve multiple instances of <see cref="IAgentAccessor"/>.
14+
/// An inner service collection used to configure and resolve multiple instances of <see cref="IAgentAccessor"/>.
1315
/// </summary>
1416
public IServiceCollection ServiceCollection { get; } = new ServiceCollection();
17+
18+
/// <summary>
19+
/// If any of the instances of <see cref="IAgentAccessor"/> which are added to <see cref="ServiceCollection"/>
20+
/// have required dependencies that live in the outer service provider (the one constructing <see cref="AgentAccessorChainOptions"/>),
21+
/// then you can specify them here.
22+
/// </summary>
23+
/// <remarks>
24+
/// Note that the <see cref="ServiceLifetime.Scoped">ServiceLifetime.Scoped</see> is not supported,
25+
/// and if the outer service is itself scoped, the agent accessor will not be able to receive it
26+
/// because it is, itself, registered as a singleton service.
27+
/// </remarks>
28+
public Dictionary<Type, ServiceLifetime> RequiredOuterServices { get; } = new();
1529
}

0 commit comments

Comments
 (0)