-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathConfiguration.cs
More file actions
196 lines (163 loc) · 6.19 KB
/
Copy pathConfiguration.cs
File metadata and controls
196 lines (163 loc) · 6.19 KB
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
namespace Microsoft.Extensions.Configuration
{
/// <summary>
/// Configuration is mutable configuration object. It is both a configuration builder and an IConfigurationRoot.
/// As sources are added, it updates its current view of configuration. Once Build is called, configuration is frozen.
/// </summary>
public class Configuration : IConfigurationRoot, IConfigurationBuilder
{
private readonly ConfigurationBuilder _builder = new ConfigurationBuilder();
private IConfigurationRoot _configuration;
/// <summary>
/// Gets or sets a configuration value.
/// </summary>
/// <param name="key">The configuration key.</param>
/// <returns>The configuration value.</returns>
public string this[string key] { get => _configuration[key]; set => _configuration[key] = value; }
/// <summary>
/// Gets a configuration sub-section with the specified key.
/// </summary>
/// <param name="key">The key of the configuration section.</param>
/// <returns>The <see cref="IConfigurationSection"/>.</returns>
/// <remarks>
/// This method will never return <c>null</c>. If no matching sub-section is found with the specified key,
/// an empty <see cref="IConfigurationSection"/> will be returned.
/// </remarks>
public IConfigurationSection GetSection(string key)
{
return _configuration.GetSection(key);
}
/// <summary>
/// Gets the immediate descendant configuration sub-sections.
/// </summary>
/// <returns>The configuration sub-sections.</returns>
public IEnumerable<IConfigurationSection> GetChildren() => _configuration.GetChildren();
IDictionary<string, object> IConfigurationBuilder.Properties => _builder.Properties;
// TODO: Handle modifications to Sources and keep the configuration root in sync
IList<IConfigurationSource> IConfigurationBuilder.Sources => Sources;
internal IList<IConfigurationSource> Sources { get; }
IEnumerable<IConfigurationProvider> IConfigurationRoot.Providers => _configuration.Providers;
/// <summary>
/// Creates a new <see cref="Configuration"/>.
/// </summary>
public Configuration()
{
UpdateConfigurationRoot();
var sources = new ConfigurationSources(_builder.Sources, UpdateConfigurationRoot);
Sources = sources;
}
internal void ChangeBasePath(string path)
{
this.SetBasePath(path);
UpdateConfigurationRoot();
}
internal void ChangeFileProvider(IFileProvider fileProvider)
{
this.SetFileProvider(fileProvider);
UpdateConfigurationRoot();
}
private void UpdateConfigurationRoot()
{
var current = _configuration;
if (current is IDisposable disposable)
{
disposable.Dispose();
}
_configuration = _builder.Build();
}
IConfigurationBuilder IConfigurationBuilder.Add(IConfigurationSource source)
{
Sources.Add(source);
return this;
}
IConfigurationRoot IConfigurationBuilder.Build()
{
// No more modification is expected after this final build
UpdateConfigurationRoot();
return this;
}
IChangeToken IConfiguration.GetReloadToken()
{
// REVIEW: Is this correct?
return _configuration.GetReloadToken();
}
void IConfigurationRoot.Reload()
{
_configuration.Reload();
}
// On source modifications, we rebuild configuration
private class ConfigurationSources : IList<IConfigurationSource>
{
private readonly IList<IConfigurationSource> _sources;
private readonly Action _sourcesModified;
public ConfigurationSources(IList<IConfigurationSource> sources, Action sourcesModified)
{
_sources = sources;
_sourcesModified = sourcesModified;
}
public IConfigurationSource this[int index]
{
get => _sources[index];
set
{
_sources[index] = value;
_sourcesModified();
}
}
public int Count => _sources.Count;
public bool IsReadOnly => _sources.IsReadOnly;
public void Add(IConfigurationSource item)
{
_sources.Add(item);
_sourcesModified();
}
public void Clear()
{
_sources.Clear();
_sourcesModified();
}
public bool Contains(IConfigurationSource item)
{
return _sources.Contains(item);
}
public void CopyTo(IConfigurationSource[] array, int arrayIndex)
{
_sources.CopyTo(array, arrayIndex);
}
public IEnumerator<IConfigurationSource> GetEnumerator()
{
return _sources.GetEnumerator();
}
public int IndexOf(IConfigurationSource item)
{
return _sources.IndexOf(item);
}
public void Insert(int index, IConfigurationSource item)
{
_sources.Insert(index, item);
_sourcesModified();
}
public bool Remove(IConfigurationSource item)
{
var removed = _sources.Remove(item);
_sourcesModified();
return removed;
}
public void RemoveAt(int index)
{
_sources.RemoveAt(index);
_sourcesModified();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
}