Skip to content

Commit dd762aa

Browse files
committed
Refactored facility and extension registration.
1 parent 2abda05 commit dd762aa

File tree

32 files changed

+626
-111
lines changed

32 files changed

+626
-111
lines changed

AppCore.Extensions.sln

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ EndProject
4444
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppCore.Extensions.Hosting.Plugins.TestPlugin2", "Hosting\test\AppCore.Extensions.Hosting.Plugins.TestPlugin2\AppCore.Extensions.Hosting.Plugins.TestPlugin2.csproj", "{C74E308B-B96F-473F-AE4B-6117FDBACF4E}"
4545
EndProject
4646
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Http", "Http", "{9416DF99-18D3-4373-A517-00A65E7CC32A}"
47+
ProjectSection(SolutionItems) = preProject
48+
Http\README.md = Http\README.md
49+
EndProjectSection
4750
EndProject
4851
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B2F9DC67-6D7B-4070-8580-F401050445A9}"
4952
EndProject

DependencyInjection/src/AppCore.Extensions.DependencyInjection.Abstractions/FacilityBuilder.cs renamed to DependencyInjection/src/AppCore.Extensions.DependencyInjection.Abstractions/Facilities/FacilityBuilder.cs

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44
using System;
55
using AppCore.Diagnostics;
66
using AppCore.Extensions.DependencyInjection.Activator;
7-
using AppCore.Extensions.DependencyInjection.Facilities;
87
using Microsoft.Extensions.DependencyInjection;
98

10-
namespace AppCore.Extensions.DependencyInjection;
9+
namespace AppCore.Extensions.DependencyInjection.Facilities;
1110

1211
/// <summary>
1312
/// Provides a builder for facilities.
1413
/// </summary>
15-
public abstract class FacilityBuilder
14+
public class FacilityBuilder
1615
{
1716
/// <summary>
1817
/// Gets the <see cref="IServiceCollection"/>.
@@ -36,12 +35,6 @@ internal FacilityBuilder(IServiceCollection services, IActivator activator, Type
3635
FacilityType = facilityType;
3736
}
3837

39-
/// <summary>
40-
/// Must be implemented to add an extension to the facility.
41-
/// </summary>
42-
/// <param name="extensionType">The type of the extension.</param>
43-
protected abstract void AddExtensionCore(Type extensionType);
44-
4538
/// <summary>
4639
/// Adds an extension to the facility.
4740
/// </summary>
@@ -53,7 +46,31 @@ internal FacilityBuilder(IServiceCollection services, IActivator activator, Type
5346
/// <returns>The <see cref="FacilityBuilder"/> to allow chaining.</returns>
5447
public FacilityBuilder AddExtension(Type extensionType)
5548
{
56-
AddExtensionCore(extensionType);
49+
Ensure.Arg.NotNull(extensionType);
50+
Ensure.Arg.OfType(extensionType, typeof(IFacilityExtension<>).MakeGenericType(FacilityType));
51+
52+
var extension = (IFacilityExtension<IFacility>)Activator.CreateInstance(extensionType);
53+
extension.ConfigureServices(Services);
54+
return this;
55+
}
56+
57+
/// <summary>
58+
/// Adds facility extensions using a <see cref="IFacilityExtensionReflectionBuilder"/> to the <see cref="IServiceCollection"/>.
59+
/// </summary>
60+
/// <param name="configure">The delegate used to configure the facility extension resolvers.</param>
61+
/// <returns>The <see cref="FacilityBuilder"/>.</returns>
62+
public FacilityBuilder AddExtensionsFrom(Action<IFacilityExtensionReflectionBuilder> configure)
63+
{
64+
Ensure.Arg.NotNull(configure);
65+
66+
var reflectionBuilder = new FacilityExtensionReflectionBuilder(Activator);
67+
configure(reflectionBuilder);
68+
69+
foreach (IFacilityExtension<IFacility> extension in reflectionBuilder.Resolve(FacilityType))
70+
{
71+
extension.ConfigureServices(Services);
72+
}
73+
5774
return this;
5875
}
5976
}
@@ -69,16 +86,6 @@ internal FacilityBuilder(IServiceCollection services, IActivator activator)
6986
{
7087
}
7188

72-
/// <inheritdoc />
73-
protected override void AddExtensionCore(Type extensionType)
74-
{
75-
Ensure.Arg.NotNull(extensionType);
76-
Ensure.Arg.OfType(extensionType, typeof(IFacilityExtension<T>));
77-
78-
var extension = (IFacilityExtension<T>)Activator.CreateInstance(extensionType);
79-
extension.ConfigureServices(Services);
80-
}
81-
8289
/// <summary>
8390
/// Adds an extension to the facility.
8491
/// </summary>
@@ -90,7 +97,7 @@ protected override void AddExtensionCore(Type extensionType)
9097
/// <returns>The <see cref="FacilityBuilder{T}"/> to allow chaining.</returns>
9198
public new FacilityBuilder<T> AddExtension(Type extensionType)
9299
{
93-
AddExtensionCore(extensionType);
100+
base.AddExtension(extensionType);
94101
return this;
95102
}
96103

@@ -102,6 +109,30 @@ protected override void AddExtensionCore(Type extensionType)
102109
public FacilityBuilder<T> AddExtension<TExtension>()
103110
where TExtension : IFacilityExtension<T>
104111
{
105-
return AddExtension(typeof(TExtension));
112+
var extension = (IFacilityExtension<IFacility>)Activator.CreateInstance(typeof(TExtension));
113+
extension.ConfigureServices(Services);
114+
return this;
106115
}
107-
}
116+
117+
/// <summary>
118+
/// Adds an extension to the facility.
119+
/// </summary>
120+
/// <returns>The <see cref="FacilityBuilder{T}"/> to allow chaining.</returns>
121+
public FacilityBuilder<T> AddExtension(IFacilityExtension<T> extension)
122+
{
123+
Ensure.Arg.NotNull(extension);
124+
extension.ConfigureServices(Services);
125+
return this;
126+
}
127+
128+
/// <summary>
129+
/// Adds facility extensions using a <see cref="IFacilityExtensionReflectionBuilder"/> to the <see cref="IServiceCollection"/>.
130+
/// </summary>
131+
/// <param name="configure">The delegate used to configure the facility extension resolvers.</param>
132+
/// <returns>The <see cref="FacilityBuilder{T}"/>.</returns>
133+
public new FacilityBuilder<T> AddExtensionsFrom(Action<IFacilityExtensionReflectionBuilder> configure)
134+
{
135+
base.AddExtensionsFrom(configure);
136+
return this;
137+
}
138+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using AppCore.Diagnostics;
5+
using AppCore.Extensions.DependencyInjection.Activator;
6+
7+
namespace AppCore.Extensions.DependencyInjection.Facilities;
8+
9+
internal sealed class FacilityExtensionReflectionBuilder : IFacilityExtensionReflectionBuilder
10+
{
11+
private readonly IActivator _activator;
12+
private readonly List<IFacilityExtensionResolver> _resolvers = new();
13+
14+
public FacilityExtensionReflectionBuilder(IActivator activator)
15+
{
16+
_activator = activator;
17+
}
18+
19+
public IFacilityExtensionReflectionBuilder AddResolver(IFacilityExtensionResolver resolver)
20+
{
21+
Ensure.Arg.NotNull(resolver);
22+
_resolvers.Add(resolver);
23+
return this;
24+
}
25+
26+
public IFacilityExtensionReflectionBuilder AddResolver<T>(Action<T>? configure = null)
27+
where T : IFacilityExtensionResolver
28+
{
29+
var resolver = _activator.CreateInstance<T>();
30+
configure?.Invoke(resolver);
31+
return AddResolver(resolver);
32+
}
33+
34+
public IReadOnlyCollection<IFacilityExtension<IFacility>> Resolve(Type facilityType)
35+
{
36+
return _resolvers.SelectMany(s => s.Resolve(facilityType))
37+
.ToList()
38+
.AsReadOnly();
39+
}
40+
}

DependencyInjection/src/AppCore.Extensions.DependencyInjection.Abstractions/Facilities/FacilityReflectionBuilder.cs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Collections.ObjectModel;
67
using System.Linq;
8+
using AppCore.Diagnostics;
79
using AppCore.Extensions.DependencyInjection.Activator;
810

911
namespace AppCore.Extensions.DependencyInjection.Facilities;
1012

11-
internal class FacilityReflectionBuilder : IFacilityReflectionBuilder
13+
internal sealed class FacilityReflectionBuilder : IFacilityReflectionBuilder
1214
{
1315
private readonly IActivator _activator;
1416
private readonly List<IFacilityResolver> _resolvers = new();
17+
private Action<IFacilityExtensionReflectionBuilder>? _extensionsConfig;
1518

1619
public FacilityReflectionBuilder(IActivator activator)
1720
{
@@ -20,6 +23,7 @@ public FacilityReflectionBuilder(IActivator activator)
2023

2124
public IFacilityReflectionBuilder AddResolver(IFacilityResolver resolver)
2225
{
26+
Ensure.Arg.NotNull(resolver);
2327
_resolvers.Add(resolver);
2428
return this;
2529
}
@@ -32,10 +36,41 @@ public IFacilityReflectionBuilder AddResolver<T>(Action<T>? configure = null)
3236
return AddResolver(resolver);
3337
}
3438

35-
public IReadOnlyCollection<IFacility> Resolve()
39+
public IFacilityReflectionBuilder AddExtensionsFrom(Action<IFacilityExtensionReflectionBuilder> configure)
3640
{
37-
return _resolvers.SelectMany(s => s.Resolve())
38-
.ToList()
39-
.AsReadOnly();
41+
Ensure.Arg.NotNull(configure);
42+
_extensionsConfig = configure;
43+
return this;
44+
}
45+
46+
public IReadOnlyCollection<(IFacility,IReadOnlyCollection<IFacilityExtension<IFacility>>)> Resolve()
47+
{
48+
List<IFacility> facilities =
49+
_resolvers.SelectMany(s => s.Resolve())
50+
.ToList();
51+
52+
FacilityExtensionReflectionBuilder? extensionReflectionBuilder = null;
53+
54+
if (_extensionsConfig != null)
55+
{
56+
extensionReflectionBuilder = new FacilityExtensionReflectionBuilder(_activator);
57+
_extensionsConfig(extensionReflectionBuilder);
58+
}
59+
60+
ReadOnlyCollection<IFacilityExtension<IFacility>> emptyFacilityExtensions =
61+
new List<IFacilityExtension<IFacility>>().AsReadOnly();
62+
63+
List<(IFacility, IReadOnlyCollection<IFacilityExtension<IFacility>>)> result = new();
64+
65+
foreach (IFacility facility in facilities)
66+
{
67+
IReadOnlyCollection<IFacilityExtension<IFacility>> facilityExtensions =
68+
extensionReflectionBuilder?.Resolve(facility.GetType())
69+
?? emptyFacilityExtensions;
70+
71+
result.Add((facility, facilityExtensions));
72+
}
73+
74+
return result;
4075
}
4176
}

DependencyInjection/src/AppCore.Extensions.DependencyInjection.Abstractions/FacilityServiceCollectionExtensions.cs renamed to DependencyInjection/src/AppCore.Extensions.DependencyInjection.Abstractions/Facilities/FacilityServiceCollectionExtensions.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Copyright (c) 2018-2021 the AppCore .NET project.
33

44
using System;
5+
using System.Collections.Generic;
56
using AppCore.Diagnostics;
67
using AppCore.Extensions.DependencyInjection;
78
using AppCore.Extensions.DependencyInjection.Activator;
@@ -68,8 +69,7 @@ public static IServiceCollection AddFacility(
6869
var facility = (IFacility)activator.CreateInstance(facilityType);
6970
if (configure != null)
7071
{
71-
Type builderType = typeof(FacilityBuilder<>).MakeGenericType(facilityType);
72-
var builder = (FacilityBuilder)Activator.CreateInstance(builderType, services, activator);
72+
var builder = new FacilityBuilder(services, activator, facilityType);
7373
configure(builder);
7474
}
7575

@@ -97,9 +97,16 @@ public static IServiceCollection AddFacilitiesFrom(
9797

9898
configure(builder);
9999

100-
foreach (IFacility facility in builder.Resolve())
100+
foreach ((IFacility facility,
101+
IReadOnlyCollection<IFacilityExtension<IFacility>> facilityExtensions) in builder
102+
.Resolve())
101103
{
102104
facility.ConfigureServices(services);
105+
106+
foreach (IFacilityExtension<IFacility> facilityExtension in facilityExtensions)
107+
{
108+
facilityExtension.ConfigureServices(services);
109+
}
103110
}
104111

105112
return services;

DependencyInjection/src/AppCore.Extensions.DependencyInjection.Abstractions/Facilities/IFacilityExtension.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace AppCore.Extensions.DependencyInjection.Facilities;
88
/// <summary>
99
/// Represents an extension for a facility.
1010
/// </summary>
11-
public interface IFacilityExtension<T>
11+
public interface IFacilityExtension<out T>
1212
where T : IFacility
1313
{
1414
/// <summary>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.ComponentModel;
3+
4+
namespace AppCore.Extensions.DependencyInjection.Facilities;
5+
6+
/// <summary>
7+
/// Represents a builder for resolving facility extensions by reflection.
8+
/// </summary>
9+
public interface IFacilityExtensionReflectionBuilder
10+
{
11+
/// <summary>
12+
/// Adds a facility extension resolver to the builder.
13+
/// </summary>
14+
/// <param name="resolver">The facility extension resolver.</param>
15+
/// <returns>The <see cref="IFacilityExtensionReflectionBuilder"/> to allow chaining.</returns>
16+
[EditorBrowsable(EditorBrowsableState.Advanced)]
17+
IFacilityExtensionReflectionBuilder AddResolver(IFacilityExtensionResolver resolver);
18+
19+
/// <summary>
20+
/// Adds a facility extension resolver to the builder.
21+
/// </summary>
22+
/// <typeparam name="T">The type of the <see cref="IFacilityExtensionResolver"/>.</typeparam>
23+
/// <param name="configure">The configuration delegate.</param>
24+
/// <returns>The <see cref="IFacilityExtensionReflectionBuilder"/> to allow chaining.</returns>
25+
[EditorBrowsable(EditorBrowsableState.Advanced)]
26+
public IFacilityExtensionReflectionBuilder AddResolver<T>(Action<T>? configure = null)
27+
where T : IFacilityExtensionResolver;
28+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace AppCore.Extensions.DependencyInjection.Facilities;
5+
6+
/// <summary>
7+
/// Represents a dynamic resolver for facility extensions.
8+
/// </summary>
9+
public interface IFacilityExtensionResolver
10+
{
11+
/// <summary>
12+
/// Resolves facility extensions.
13+
/// </summary>
14+
/// <param name="facilityType">The type of the facility.</param>
15+
/// <returns>The <see cref="IEnumerable{T}"/> of facility extensions.</returns>
16+
IEnumerable<IFacilityExtension<IFacility>> Resolve(Type facilityType);
17+
}

DependencyInjection/src/AppCore.Extensions.DependencyInjection.Abstractions/Facilities/IFacilityReflectionBuilder.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,17 @@ public interface IFacilityReflectionBuilder
2222
/// <summary>
2323
/// Adds a facility resolver to the builder.
2424
/// </summary>
25-
/// <typeparam name="T">The type of the <see cref="IFacilityReflectionBuilder"/>.</typeparam>
25+
/// <typeparam name="T">The type of the <see cref="IFacilityResolver"/>.</typeparam>
2626
/// <param name="configure">The configuration delegate.</param>
2727
/// <returns>The <see cref="IFacilityReflectionBuilder"/> to allow chaining.</returns>
2828
[EditorBrowsable(EditorBrowsableState.Advanced)]
2929
public IFacilityReflectionBuilder AddResolver<T>(Action<T>? configure = null)
3030
where T : IFacilityResolver;
31+
32+
/// <summary>
33+
/// Adds extensions to the resolved facilities by reflection.
34+
/// </summary>
35+
/// <param name="configure">The configuration delegate.</param>
36+
/// <returns>The <see cref="IFacilityReflectionBuilder"/> to allow chaining.</returns>
37+
public IFacilityReflectionBuilder AddExtensionsFrom(Action<IFacilityExtensionReflectionBuilder> configure);
3138
}

0 commit comments

Comments
 (0)