4
4
using System ;
5
5
using System . Collections . Generic ;
6
6
using System . Linq ;
7
- using System . Net . Http ;
8
7
using Microsoft . AspNetCore . Components . Routing ;
9
8
using Microsoft . AspNetCore . Components . WebAssembly . Services ;
10
9
using Microsoft . Extensions . Configuration ;
@@ -20,6 +19,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
20
19
/// </summary>
21
20
public sealed class WebAssemblyHostBuilder
22
21
{
22
+ private Func < IServiceProvider > _createServiceProvider ;
23
+
23
24
/// <summary>
24
25
/// Creates an instance of <see cref="WebAssemblyHostBuilder"/> using the most common
25
26
/// conventions and settings.
@@ -53,6 +54,11 @@ private WebAssemblyHostBuilder()
53
54
Services = new ServiceCollection ( ) ;
54
55
55
56
InitializeDefaultServices ( ) ;
57
+
58
+ _createServiceProvider = ( ) =>
59
+ {
60
+ return Services . BuildServiceProvider ( ) ;
61
+ } ;
56
62
}
57
63
58
64
/// <summary>
@@ -71,6 +77,40 @@ private WebAssemblyHostBuilder()
71
77
/// </summary>
72
78
public IServiceCollection Services { get ; }
73
79
80
+ /// <summary>
81
+ /// Registers a <see cref="IServiceProviderFactory{TBuilder}" /> instance to be used to create the <see cref="IServiceProvider" />.
82
+ /// </summary>
83
+ /// <param name="factory">The <see cref="IServiceProviderFactory{TBuilder}" />.</param>
84
+ /// <param name="configure">
85
+ /// A delegate used to configure the <typeparamref T="TBuilder" />. This can be used to configure services using
86
+ /// APIS specific to the <see cref="IServiceProviderFactory{TBuilder}" /> implementation.
87
+ /// </param>
88
+ /// <typeparam name="TBuilder">The type of builder provided by the <see cref="IServiceProviderFactory{TBuilder}" />.</typeparam>
89
+ /// <remarks>
90
+ /// <para>
91
+ /// <see cref="ConfigureContainer{TBuilder}(IServiceProviderFactory{TBuilder}, Action{TBuilder})"/> is called by <see cref="Build"/>
92
+ /// and so the delegate provided by <paramref name="configure"/> will run after all other services have been registered.
93
+ /// </para>
94
+ /// <para>
95
+ /// Multiple calls to <see cref="ConfigureContainer{TBuilder}(IServiceProviderFactory{TBuilder}, Action{TBuilder})"/> will replace
96
+ /// the previously stored <paramref name="factory"/> and <paramref name="configure"/> delegate.
97
+ /// </para>
98
+ /// </remarks>
99
+ public void ConfigureContainer < TBuilder > ( IServiceProviderFactory < TBuilder > factory , Action < TBuilder > configure = null )
100
+ {
101
+ if ( factory == null )
102
+ {
103
+ throw new ArgumentNullException ( nameof ( factory ) ) ;
104
+ }
105
+
106
+ _createServiceProvider = ( ) =>
107
+ {
108
+ var container = factory . CreateBuilder ( Services ) ;
109
+ configure ? . Invoke ( container ) ;
110
+ return factory . CreateServiceProvider ( container ) ;
111
+ } ;
112
+ }
113
+
74
114
/// <summary>
75
115
/// Builds a <see cref="WebAssemblyHost"/> instance based on the configuration of this builder.
76
116
/// </summary>
@@ -84,7 +124,7 @@ public WebAssemblyHost Build()
84
124
// A Blazor application always runs in a scope. Since we want to make it possible for the user
85
125
// to configure services inside *that scope* inside their startup code, we create *both* the
86
126
// service provider and the scope here.
87
- var services = Services . BuildServiceProvider ( ) ;
127
+ var services = _createServiceProvider ( ) ;
88
128
var scope = services . GetRequiredService < IServiceScopeFactory > ( ) . CreateScope ( ) ;
89
129
90
130
return new WebAssemblyHost ( services , scope , configuration , RootComponents . ToArray ( ) ) ;
0 commit comments