/
ClientBuilder.cs
160 lines (140 loc) · 6.59 KB
/
ClientBuilder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Orleans.Hosting;
using Orleans.ApplicationParts;
using Orleans.Serialization;
using Microsoft.Extensions.Hosting;
using IHostingEnvironment = Orleans.Hosting.IHostingEnvironment;
using HostBuilderContext = Orleans.Hosting.HostBuilderContext;
using HostDefaults = Orleans.Hosting.HostDefaults;
using EnvironmentName = Orleans.Hosting.EnvironmentName;
namespace Orleans
{
/// <summary>
/// Builder used for creating <see cref="IClusterClient"/> instances.
/// </summary>
public class ClientBuilder : IClientBuilder
{
private readonly ServiceProviderBuilder serviceProviderBuilder = new ServiceProviderBuilder();
private readonly List<Action<IConfigurationBuilder>> configureHostConfigActions = new List<Action<IConfigurationBuilder>>();
private readonly List<Action<HostBuilderContext, IConfigurationBuilder>> configureAppConfigActions = new List<Action<HostBuilderContext, IConfigurationBuilder>>();
private HostBuilderContext hostBuilderContext;
private IConfiguration hostConfiguration;
private IConfiguration appConfiguration;
private IHostingEnvironment hostingEnvironment;
private bool built;
/// <inheritdoc />
public IDictionary<object, object> Properties { get; } = new Dictionary<object, object>();
/// <inheritdoc />
public IClusterClient Build()
{
if (this.built) throw new InvalidOperationException($"{nameof(this.Build)} may only be called once per {nameof(ClientBuilder)} instance.");
this.built = true;
// Configure default services and build the container.
this.ConfigureDefaults();
BuildHostConfiguration();
CreateHostingEnvironment();
CreateHostBuilderContext();
BuildAppConfiguration();
this.ConfigureServices(
services =>
{
services.AddSingleton(this.hostingEnvironment);
services.AddSingleton(this.hostBuilderContext);
services.AddSingleton(this.appConfiguration);
services.AddSingleton<IHostApplicationLifetime, ClientApplicationLifetime>();
services.AddOptions();
services.AddLogging();
});
var serviceProvider = this.serviceProviderBuilder.BuildServiceProvider(this.hostBuilderContext);
ValidateSystemConfiguration(serviceProvider);
// Construct and return the cluster client.
serviceProvider.GetService<SerializationManager>().RegisterSerializers(serviceProvider.GetService<IApplicationPartManager>());
serviceProvider.GetRequiredService<OutsideRuntimeClient>().ConsumeServices(serviceProvider);
return serviceProvider.GetRequiredService<IClusterClient>();
}
/// <inheritdoc />
public IClientBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate)
{
this.configureHostConfigActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate)));
return this;
}
/// <inheritdoc />
public IClientBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate)
{
this.configureAppConfigActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate)));
return this;
}
/// <inheritdoc />
public IClientBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
{
if (configureDelegate == null) throw new ArgumentNullException(nameof(configureDelegate));
this.serviceProviderBuilder.ConfigureServices(configureDelegate);
return this;
}
/// <inheritdoc />
public IClientBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory)
{
this.serviceProviderBuilder.UseServiceProviderFactory(factory);
return this;
}
/// <inheritdoc />
public IClientBuilder ConfigureContainer<TContainerBuilder>(Action<TContainerBuilder> configureContainer)
{
this.serviceProviderBuilder.ConfigureContainer((HostBuilderContext context, TContainerBuilder containerBuilder) => configureContainer(containerBuilder));
return this;
}
private static void ValidateSystemConfiguration(IServiceProvider serviceProvider)
{
var validators = serviceProvider.GetServices<IConfigurationValidator>();
foreach (var validator in validators)
{
validator.ValidateConfiguration();
}
}
private void CreateHostBuilderContext()
{
this.hostBuilderContext = new HostBuilderContext(this.Properties)
{
HostingEnvironment = this.hostingEnvironment,
Configuration = this.hostConfiguration
};
}
private void CreateHostingEnvironment()
{
this.hostingEnvironment = new HostingEnvironment()
{
ApplicationName = this.hostConfiguration[HostDefaults.ApplicationKey],
EnvironmentName = this.hostConfiguration[HostDefaults.EnvironmentKey] ?? EnvironmentName.Production,
};
}
private void BuildHostConfiguration()
{
var configBuilder = new ConfigurationBuilder();
foreach (var buildAction in this.configureHostConfigActions)
{
buildAction(configBuilder);
}
this.hostConfiguration = configBuilder.Build();
}
private void BuildAppConfiguration()
{
var configBuilder = new ConfigurationBuilder();
// replace with: configBuilder.AddConfiguration(this.hostConfiguration);
// This method was added post v2.0.0 of Microsoft.Extensions.Configuration
foreach (var buildAction in this.configureHostConfigActions)
{
buildAction(configBuilder);
}
// end replace
foreach (var buildAction in this.configureAppConfigActions)
{
buildAction(this.hostBuilderContext, configBuilder);
}
this.appConfiguration = configBuilder.Build();
this.hostBuilderContext.Configuration = this.appConfiguration;
}
}
}