Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit a77e7cf

Browse files
committed
Allow ConfigureServices to be called multiple times.
1 parent b48b5f1 commit a77e7cf

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Diagnostics;
67
using System.IO;
78
using System.Reflection;
@@ -28,12 +29,11 @@ public class WebHostBuilder : IWebHostBuilder
2829
{
2930
private readonly IHostingEnvironment _hostingEnvironment;
3031
private readonly ILoggerFactory _loggerFactory;
32+
private readonly List<Action<IServiceCollection>> _configureServicesDelegates;
3133

3234
private IConfiguration _config = new ConfigurationBuilder().AddInMemoryCollection().Build();
3335
private WebHostOptions _options;
3436

35-
private Action<IServiceCollection> _configureServices;
36-
3737
// Only one of these should be set
3838
private StartupMethods _startup;
3939
private Type _startupType;
@@ -45,6 +45,7 @@ public WebHostBuilder()
4545
{
4646
_hostingEnvironment = new HostingEnvironment();
4747
_loggerFactory = new LoggerFactory();
48+
_configureServicesDelegates = new List<Action<IServiceCollection>>();
4849
}
4950

5051
/// <summary>
@@ -102,13 +103,19 @@ public IWebHostBuilder UseStartup(Type startupType)
102103
}
103104

104105
/// <summary>
105-
/// Specify the delegate that is used to configure the services of the web application.
106+
/// Adds a delegate for configuring additional services for the host or web application. This may be called
107+
/// multiple times.
106108
/// </summary>
107-
/// <param name="configureServices">The delegate that configures the <see cref="IServiceCollection"/>.</param>
109+
/// <param name="configureServices">A delegate for configuring the <see cref="IServiceCollection"/>.</param>
108110
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
109111
public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
110112
{
111-
_configureServices = configureServices;
113+
if (configureServices == null)
114+
{
115+
throw new ArgumentNullException(nameof(configureServices));
116+
}
117+
118+
_configureServicesDelegates.Add(configureServices);
112119
return this;
113120
}
114121

@@ -213,9 +220,9 @@ private IServiceCollection BuildHostingServices()
213220
}
214221
}
215222

216-
if (_configureServices != null)
223+
foreach (var configureServices in _configureServicesDelegates)
217224
{
218-
_configureServices(services);
225+
configureServices(services);
219226
}
220227

221228
return services;

test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,31 @@ public void UseCaptureStartupErrorsHonored()
148148
Assert.Equal("A public method named 'ConfigureProduction' or 'Configure' could not be found in the 'Microsoft.AspNetCore.Hosting.Fakes.StartupBoom' type.", exception.Message);
149149
}
150150

151+
[Fact]
152+
public void ConfigureServices_CanBeCalledMultipleTimes()
153+
{
154+
var callCount = 0; // Verify ordering
155+
var hostBuilder = new WebHostBuilder()
156+
.UseServer(new TestServer())
157+
.ConfigureServices(services =>
158+
{
159+
Assert.Equal(0, callCount++);
160+
services.AddTransient<ServiceA>();
161+
})
162+
.ConfigureServices(services =>
163+
{
164+
Assert.Equal(1, callCount++);
165+
services.AddTransient<ServiceB>();
166+
})
167+
.Configure(app => { });
168+
169+
var host = hostBuilder.Build();
170+
Assert.Equal(2, callCount);
171+
172+
Assert.NotNull(host.Services.GetRequiredService<ServiceA>());
173+
Assert.NotNull(host.Services.GetRequiredService<ServiceB>());
174+
}
175+
151176
[Fact]
152177
public void CodeBasedSettingsCodeBasedOverride()
153178
{
@@ -418,5 +443,15 @@ public void Start<TContext>(IHttpApplication<TContext> application)
418443
};
419444
}
420445
}
446+
447+
private class ServiceA
448+
{
449+
450+
}
451+
452+
private class ServiceB
453+
{
454+
455+
}
421456
}
422457
}

0 commit comments

Comments
 (0)