├── .appveyor.yml ├── .gitattributes ├── .gitignore ├── .travis.yml ├── .vsts-pipelines └── builds │ ├── ci-internal.yml │ └── ci-public.yml ├── CONTRIBUTING.md ├── Configuration.sln ├── Directory.Build.props ├── Directory.Build.targets ├── LICENSE.txt ├── NuGet.config ├── NuGetPackageVerifier.json ├── README.md ├── build.cmd ├── build.sh ├── build ├── Key.snk ├── dependencies.props ├── repo.props └── sources.props ├── korebuild-lock.txt ├── korebuild.json ├── run.cmd ├── run.ps1 ├── run.sh ├── samples └── KeyVaultSample │ ├── EnvironmentSecretManager.cs │ ├── KeyVaultSample.csproj │ ├── Program.cs │ └── settings.json ├── src ├── Config.Abstractions │ ├── Config.Abstractions.csproj │ ├── ConfigurationExtensions.cs │ ├── ConfigurationPath.cs │ ├── IConfiguration.cs │ ├── IConfigurationBuilder.cs │ ├── IConfigurationProvider.cs │ ├── IConfigurationRoot.cs │ ├── IConfigurationSection.cs │ ├── IConfigurationSource.cs │ └── baseline.netcore.json ├── Config.AzureKeyVault │ ├── AzureKeyVaultConfigurationExtensions.cs │ ├── AzureKeyVaultConfigurationProvider.cs │ ├── AzureKeyVaultConfigurationSource.cs │ ├── Config.AzureKeyVault.csproj │ ├── DefaultKeyVaultSecretManager.cs │ ├── IKeyVaultClient.cs │ ├── IKeyVaultSecretManager.cs │ ├── KeyVaultClientWrapper.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── baseline.netcore.json ├── Config.Binder │ ├── BinderOptions.cs │ ├── Config.Binder.csproj │ ├── ConfigurationBinder.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── Resources.resx │ └── baseline.netcore.json ├── Config.CommandLine │ ├── CommandLineConfigurationExtensions.cs │ ├── CommandLineConfigurationProvider.cs │ ├── CommandLineConfigurationSource.cs │ ├── Config.CommandLine.csproj │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── Resources.resx │ └── baseline.netcore.json ├── Config.EnvironmentVariables │ ├── Config.EnvironmentVariables.csproj │ ├── EnvironmentVariablesConfigurationProvider.cs │ ├── EnvironmentVariablesConfigurationSource.cs │ ├── EnvironmentVariablesExtensions.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── baseline.netcore.json ├── Config.FileExtensions │ ├── Config.FileExtensions.csproj │ ├── FileConfigurationExtensions.cs │ ├── FileConfigurationProvider.cs │ ├── FileConfigurationSource.cs │ ├── FileLoadExceptionContext.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── Resources.resx │ └── baseline.netcore.json ├── Config.Ini │ ├── Config.Ini.csproj │ ├── IniConfigurationExtensions.cs │ ├── IniConfigurationProvider.cs │ ├── IniConfigurationSource.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── Resources.resx │ └── baseline.netcore.json ├── Config.Json │ ├── Config.Json.csproj │ ├── JsonConfigurationExtensions.cs │ ├── JsonConfigurationFileParser.cs │ ├── JsonConfigurationProvider.cs │ ├── JsonConfigurationSource.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── Resources.resx │ └── baseline.netcore.json ├── Config.KeyPerFile │ ├── Config.KeyPerFile.csproj │ ├── KeyPerFileConfigurationBuilderExtensions.cs │ ├── KeyPerFileConfigurationProvider.cs │ ├── KeyPerFileConfigurationSource.cs │ └── README.md ├── Config.UserSecrets │ ├── Config.UserSecrets.csproj │ ├── PathHelper.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── Resources.resx │ ├── UserSecretsConfigurationExtensions.cs │ ├── UserSecretsIdAttribute.cs │ ├── baseline.netcore.json │ └── build │ │ └── netstandard2.0 │ │ ├── Microsoft.Extensions.Configuration.UserSecrets.props │ │ └── Microsoft.Extensions.Configuration.UserSecrets.targets ├── Config.Xml │ ├── Config.Xml.csproj │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── Resources.resx │ ├── XmlConfigurationExtensions.cs │ ├── XmlConfigurationProvider.cs │ ├── XmlConfigurationSource.cs │ ├── XmlDocumentDecryptor.cs │ └── baseline.netcore.json ├── Config │ ├── ChainedBuilderExtensions.cs │ ├── ChainedConfigurationProvider.cs │ ├── ChainedConfigurationSource.cs │ ├── Config.csproj │ ├── ConfigurationBuilder.cs │ ├── ConfigurationKeyComparer.cs │ ├── ConfigurationProvider.cs │ ├── ConfigurationReloadToken.cs │ ├── ConfigurationRoot.cs │ ├── ConfigurationSection.cs │ ├── MemoryConfigurationBuilderExtensions.cs │ ├── MemoryConfigurationProvider.cs │ ├── MemoryConfigurationSource.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── Resources.resx │ └── baseline.netcore.json └── Directory.Build.props ├── test ├── Config.AzureKeyVault.Test │ ├── AzureKeyVaultConfigurationTest.cs │ └── Config.AzureKeyVault.Test.csproj ├── Config.Binder.Test │ ├── Config.Binder.Test.csproj │ ├── ConfigurationBinderTests.cs │ └── ConfigurationCollectionBindingTests.cs ├── Config.CommandLine.Test │ ├── CommandLineTest.cs │ └── Config.CommandLine.Test.csproj ├── Config.EnvironmentVariables.Test │ ├── Config.EnvironmentVariables.Test.csproj │ └── EnvironmentVariablesTest.cs ├── Config.FileExtensions.Test │ ├── Config.FileExtensions.Test.csproj │ └── FileConfigurationBuilderExtensionsTest.cs ├── Config.FunctionalTests │ ├── ArrayTests.cs │ ├── Config.FunctionalTests.csproj │ ├── ConfigurationTests.cs │ ├── DisposableFileSystem.cs │ └── test.xml ├── Config.Ini.Test │ ├── Config.Ini.Test.csproj │ ├── IniConfigurationExtensionsTest.cs │ └── IniConfigurationTest.cs ├── Config.Json.Test │ ├── ArrayTest.cs │ ├── Config.Json.Test.csproj │ ├── JsonConfigurationExtensionsTest.cs │ └── JsonConfigurationTest.cs ├── Config.KeyPerFile.Test │ ├── Config.KeyPerFile.Test.csproj │ └── KeyPerFileTests.cs ├── Config.Test.Common │ ├── Config.Test.Common.csproj │ ├── ConfigurationProviderExtensions.cs │ └── TestStreamHelpers.cs ├── Config.Test │ ├── Config.Test.csproj │ ├── ConfigurationPathComparerTest.cs │ ├── ConfigurationPathTest.cs │ └── ConfigurationTest.cs ├── Config.UserSecrets.Test │ ├── Config.UserSecrets.Test.csproj │ ├── ConfigurationExtensionTest.cs │ ├── MsBuildTargetTest.cs │ └── PathHelperTest.cs ├── Config.Xml.Test │ ├── Config.Xml.Test.csproj │ ├── XmlConfigurationExtensionsTest.cs │ └── XmlConfigurationTest.cs └── Directory.Build.props └── version.props /.appveyor.yml: -------------------------------------------------------------------------------- 1 | init: 2 | - git config --global core.autocrlf true 3 | branches: 4 | only: 5 | - master 6 | - /^release\/.*$/ 7 | - /^(.*\/)?ci-.*$/ 8 | build_script: 9 | - ps: .\run.ps1 default-build 10 | clone_depth: 1 11 | environment: 12 | global: 13 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 14 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 15 | test: 'off' 16 | deploy: 'off' 17 | os: Visual Studio 2017 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | 12 | *.jpg binary 13 | *.png binary 14 | *.gif binary 15 | 16 | *.cs text=auto diff=csharp 17 | *.vb text=auto 18 | *.resx text=auto 19 | *.c text=auto 20 | *.cpp text=auto 21 | *.cxx text=auto 22 | *.h text=auto 23 | *.hxx text=auto 24 | *.py text=auto 25 | *.rb text=auto 26 | *.java text=auto 27 | *.html text=auto 28 | *.htm text=auto 29 | *.css text=auto 30 | *.scss text=auto 31 | *.sass text=auto 32 | *.less text=auto 33 | *.js text=auto 34 | *.lisp text=auto 35 | *.clj text=auto 36 | *.sql text=auto 37 | *.php text=auto 38 | *.lua text=auto 39 | *.m text=auto 40 | *.asm text=auto 41 | *.erl text=auto 42 | *.fs text=auto 43 | *.fsx text=auto 44 | *.hs text=auto 45 | 46 | *.csproj text=auto 47 | *.vbproj text=auto 48 | *.fsproj text=auto 49 | *.dbproj text=auto 50 | *.sln text=auto eol=crlf 51 | *.sh eol=lf 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj/ 2 | [Bb]in/ 3 | TestResults/ 4 | .nuget/ 5 | _ReSharper.*/ 6 | packages/ 7 | artifacts/ 8 | PublishProfiles/ 9 | *.user 10 | *.suo 11 | *.cache 12 | *.docstates 13 | _ReSharper.* 14 | nuget.exe 15 | *net45.csproj 16 | *net451.csproj 17 | *k10.csproj 18 | *.psess 19 | *.vsp 20 | *.pidb 21 | *.userprefs 22 | *DS_Store 23 | *.ncrunchsolution 24 | *.*sdf 25 | *.ipch 26 | *.sln.ide 27 | project.lock.json 28 | .vs 29 | .vscode/ 30 | .build/ 31 | .testPublish/ 32 | *.nuget.props 33 | *.nuget.targets 34 | global.json 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | sudo: false 3 | dist: trusty 4 | env: 5 | global: 6 | - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 7 | - DOTNET_CLI_TELEMETRY_OPTOUT: 1 8 | mono: none 9 | os: 10 | - linux 11 | - osx 12 | osx_image: xcode8.2 13 | addons: 14 | apt: 15 | packages: 16 | - libunwind8 17 | branches: 18 | only: 19 | - master 20 | - /^release\/.*$/ 21 | - /^(.*\/)?ci-.*$/ 22 | before_install: 23 | - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s 24 | /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib 25 | /usr/local/lib/; fi 26 | script: 27 | - ./build.sh 28 | -------------------------------------------------------------------------------- /.vsts-pipelines/builds/ci-internal.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | - release/* 4 | 5 | resources: 6 | repositories: 7 | - repository: buildtools 8 | type: git 9 | name: aspnet-BuildTools 10 | ref: refs/heads/master 11 | 12 | phases: 13 | - template: .vsts-pipelines/templates/project-ci.yml@buildtools 14 | -------------------------------------------------------------------------------- /.vsts-pipelines/builds/ci-public.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | - release/* 4 | 5 | # See https://github.com/aspnet/BuildTools 6 | resources: 7 | repositories: 8 | - repository: buildtools 9 | type: github 10 | endpoint: DotNet-Bot GitHub Connection 11 | name: aspnet/BuildTools 12 | ref: refs/heads/master 13 | 14 | phases: 15 | - template: .vsts-pipelines/templates/project-ci.yml@buildtools 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ====== 3 | 4 | Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo. 5 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Microsoft .NET Extensions 12 | https://github.com/aspnet/Configuration 13 | git 14 | $(MSBuildThisFileDirectory) 15 | $(MSBuildThisFileDirectory)build\Key.snk 16 | true 17 | true 18 | 19 | 20 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(MicrosoftNETCoreApp20PackageVersion) 4 | $(MicrosoftNETCoreApp21PackageVersion) 5 | $(MicrosoftNETCoreApp22PackageVersion) 6 | $(NETStandardLibrary20PackageVersion) 7 | 8 | 99.9 9 | 10 | 11 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NuGetPackageVerifier.json: -------------------------------------------------------------------------------- 1 | { 2 | "Default": { 3 | "rules": [ 4 | "DefaultCompositeRule" 5 | ] 6 | } 7 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Configuration [Archived] 2 | ======================== 3 | 4 | **This GitHub project has been archived.** Ongoing development on this project can be found in . 5 | 6 | Configuration is a framework for accessing Key/Value based configuration settings in an application. Includes configuration providers for command line arguments, environment variables, INI files, JSON files, and XML files. 7 | 8 | This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [AspNetCore](https://github.com/aspnet/AspNetCore) repo. 9 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" 3 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | # Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) 7 | chmod +x "$DIR/run.sh"; sync 8 | "$DIR/run.sh" default-build "$@" 9 | -------------------------------------------------------------------------------- /build/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/Configuration/f64994e0655659faefccead7ccb5c1edbfd4d4ba/build/Key.snk -------------------------------------------------------------------------------- /build/dependencies.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 4 | 5 | 6 | 3.0.0-alpha1-20181004.7 7 | 3.0.0-alpha1-10584 8 | 2.3.2 9 | 1.0.1 10 | 3.0.0-alpha1-10584 11 | 3.0.0-alpha1-10584 12 | 2.0.9 13 | 2.1.3 14 | 2.2.0-preview2-26905-02 15 | 15.6.1 16 | 4.9.0 17 | 2.0.3 18 | 11.0.2 19 | 4.6.0-preview1-26907-04 20 | 2.3.1 21 | 2.4.0 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /build/repo.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Internal.AspNetCore.Universe.Lineup 11 | https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /build/sources.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $(DotNetRestoreSources) 6 | 7 | $(RestoreSources); 8 | https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; 9 | https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; 10 | https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; 11 | 12 | 13 | $(RestoreSources); 14 | https://api.nuget.org/v3/index.json; 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /korebuild-lock.txt: -------------------------------------------------------------------------------- 1 | version:3.0.0-alpha1-20181004.7 2 | commithash:27fabdaf2b1d4753c3d2749581694ca65d78f7f2 3 | -------------------------------------------------------------------------------- /korebuild.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", 3 | "channel": "master" 4 | } 5 | -------------------------------------------------------------------------------- /run.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" 3 | -------------------------------------------------------------------------------- /samples/KeyVaultSample/EnvironmentSecretManager.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.KeyVault.Models; 2 | using Microsoft.Extensions.Configuration.AzureKeyVault; 3 | 4 | namespace ConsoleApplication 5 | { 6 | public class EnvironmentSecretManager : DefaultKeyVaultSecretManager 7 | { 8 | private readonly string _environmentPrefix; 9 | 10 | public EnvironmentSecretManager(string environment) 11 | { 12 | _environmentPrefix = environment + "-"; 13 | } 14 | 15 | public override bool Load(SecretItem secret) 16 | { 17 | return HasEnvironmentPrefix(secret.Identifier.Name); 18 | } 19 | 20 | public override string GetKey(SecretBundle secret) 21 | { 22 | var keyName = base.GetKey(secret); 23 | 24 | return HasEnvironmentPrefix(keyName) 25 | ? keyName.Substring(_environmentPrefix.Length) 26 | : keyName; 27 | } 28 | 29 | private bool HasEnvironmentPrefix(string name) 30 | { 31 | return name.StartsWith(_environmentPrefix); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /samples/KeyVaultSample/KeyVaultSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2;net461 5 | portable 6 | Exe 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/KeyVaultSample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography.X509Certificates; 5 | using Microsoft.Extensions.Configuration; 6 | 7 | namespace ConsoleApplication 8 | { 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | var builder = new ConfigurationBuilder(); 14 | builder.AddJsonFile("settings.json"); 15 | 16 | var config = builder.Build(); 17 | 18 | var store = new X509Store(StoreLocation.CurrentUser); 19 | store.Open(OpenFlags.ReadOnly); 20 | var cert = store.Certificates.Find(X509FindType.FindByThumbprint, config["CertificateThumbprint"], false); 21 | 22 | builder.AddAzureKeyVault( 23 | config["Vault"], 24 | config["ClientId"], 25 | cert.OfType().Single(), 26 | new EnvironmentSecretManager("Development")); 27 | store.Close(); 28 | 29 | config = builder.Build(); 30 | 31 | Console.WriteLine(config["ConnectionString"]); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /samples/KeyVaultSample/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CertificateThumbprint": "", 3 | "Vault": "", 4 | "ClientId": "" 5 | } 6 | -------------------------------------------------------------------------------- /src/Config.Abstractions/Config.Abstractions.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Abstractions 5 | Microsoft.Extensions.Configuration.Abstractions 6 | Abstractions of key-value pair based configuration. 7 | Commonly used types: 8 | Microsoft.Extensions.Configuration.IConfiguration 9 | Microsoft.Extensions.Configuration.IConfigurationBuilder 10 | Microsoft.Extensions.Configuration.IConfigurationProvider 11 | Microsoft.Extensions.Configuration.IConfigurationRoot 12 | Microsoft.Extensions.Configuration.IConfigurationSection 13 | netstandard2.0 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Config.Abstractions/ConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace Microsoft.Extensions.Configuration 9 | { 10 | /// 11 | /// Extension methods for configuration classes./>. 12 | /// 13 | public static class ConfigurationExtensions 14 | { 15 | /// 16 | /// Adds a new configuration source. 17 | /// 18 | /// The to add to. 19 | /// Configures the source secrets. 20 | /// The . 21 | public static IConfigurationBuilder Add(this IConfigurationBuilder builder, Action configureSource) where TSource : IConfigurationSource, new() 22 | { 23 | var source = new TSource(); 24 | configureSource?.Invoke(source); 25 | return builder.Add(source); 26 | } 27 | 28 | /// 29 | /// Shorthand for GetSection("ConnectionStrings")[name]. 30 | /// 31 | /// The configuration. 32 | /// The connection string key. 33 | /// 34 | public static string GetConnectionString(this IConfiguration configuration, string name) 35 | { 36 | return configuration?.GetSection("ConnectionStrings")?[name]; 37 | } 38 | 39 | /// 40 | /// Get the enumeration of key value pairs within the 41 | /// 42 | /// The to enumerate. 43 | /// An enumeration of key value pairs. 44 | public static IEnumerable> AsEnumerable(this IConfiguration configuration) => configuration.AsEnumerable(makePathsRelative: false); 45 | 46 | /// 47 | /// Get the enumeration of key value pairs within the 48 | /// 49 | /// The to enumerate. 50 | /// If true, the child keys returned will have the current configuration's Path trimmed from the front. 51 | /// An enumeration of key value pairs. 52 | public static IEnumerable> AsEnumerable(this IConfiguration configuration, bool makePathsRelative) 53 | { 54 | var stack = new Stack(); 55 | stack.Push(configuration); 56 | var rootSection = configuration as IConfigurationSection; 57 | var prefixLength = (makePathsRelative && rootSection != null) ? rootSection.Path.Length + 1 : 0; 58 | while (stack.Count > 0) 59 | { 60 | var config = stack.Pop(); 61 | // Don't include the sections value if we are removing paths, since it will be an empty key 62 | if (config is IConfigurationSection section && (!makePathsRelative || config != configuration)) 63 | { 64 | yield return new KeyValuePair(section.Path.Substring(prefixLength), section.Value); 65 | } 66 | foreach (var child in config.GetChildren()) 67 | { 68 | stack.Push(child); 69 | } 70 | } 71 | } 72 | 73 | /// 74 | /// Determines whether the section has a or has children 75 | /// 76 | public static bool Exists(this IConfigurationSection section) 77 | { 78 | if (section == null) 79 | { 80 | return false; 81 | } 82 | return section.Value != null || section.GetChildren().Any(); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/Config.Abstractions/ConfigurationPath.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// Utility methods and constants for manipulating Configuration paths 11 | /// 12 | public static class ConfigurationPath 13 | { 14 | /// 15 | /// The delimiter ":" used to separate individual keys in a path. 16 | /// 17 | public static readonly string KeyDelimiter = ":"; 18 | 19 | /// 20 | /// Combines path segments into one path. 21 | /// 22 | /// The path segments to combine. 23 | /// The combined path. 24 | public static string Combine(params string[] pathSegments) 25 | { 26 | if (pathSegments == null) 27 | { 28 | throw new ArgumentNullException(nameof(pathSegments)); 29 | } 30 | return string.Join(KeyDelimiter, pathSegments); 31 | } 32 | 33 | /// 34 | /// Combines path segments into one path. 35 | /// 36 | /// The path segments to combine. 37 | /// The combined path. 38 | public static string Combine(IEnumerable pathSegments) 39 | { 40 | if (pathSegments == null) 41 | { 42 | throw new ArgumentNullException(nameof(pathSegments)); 43 | } 44 | return string.Join(KeyDelimiter, pathSegments); 45 | } 46 | 47 | /// 48 | /// Extracts the last path segment from the path. 49 | /// 50 | /// The path. 51 | /// The last path segment of the path. 52 | public static string GetSectionKey(string path) 53 | { 54 | if (string.IsNullOrEmpty(path)) 55 | { 56 | return path; 57 | } 58 | 59 | var lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase); 60 | return lastDelimiterIndex == -1 ? path : path.Substring(lastDelimiterIndex + 1); 61 | } 62 | 63 | /// 64 | /// Extracts the path corresponding to the parent node for a given path. 65 | /// 66 | /// The path. 67 | /// The original path minus the last individual segment found in it. Null if the original path corresponds to a top level node. 68 | public static string GetParentPath(string path) 69 | { 70 | if (string.IsNullOrEmpty(path)) 71 | { 72 | return null; 73 | } 74 | 75 | var lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase); 76 | return lastDelimiterIndex == -1 ? null : path.Substring(0, lastDelimiterIndex); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Config.Abstractions/IConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | using Microsoft.Extensions.Primitives; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// Represents a set of key/value application configuration properties. 11 | /// 12 | public interface IConfiguration 13 | { 14 | /// 15 | /// Gets or sets a configuration value. 16 | /// 17 | /// The configuration key. 18 | /// The configuration value. 19 | string this[string key] { get; set; } 20 | 21 | /// 22 | /// Gets a configuration sub-section with the specified key. 23 | /// 24 | /// The key of the configuration section. 25 | /// The . 26 | /// 27 | /// This method will never return null. If no matching sub-section is found with the specified key, 28 | /// an empty will be returned. 29 | /// 30 | IConfigurationSection GetSection(string key); 31 | 32 | /// 33 | /// Gets the immediate descendant configuration sub-sections. 34 | /// 35 | /// The configuration sub-sections. 36 | IEnumerable GetChildren(); 37 | 38 | /// 39 | /// Returns a that can be used to observe when this configuration is reloaded. 40 | /// 41 | /// A . 42 | IChangeToken GetReloadToken(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Config.Abstractions/IConfigurationBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.Extensions.Configuration 7 | { 8 | /// 9 | /// Represents a type used to build application configuration. 10 | /// 11 | public interface IConfigurationBuilder 12 | { 13 | /// 14 | /// Gets a key/value collection that can be used to share data between the 15 | /// and the registered s. 16 | /// 17 | IDictionary Properties { get; } 18 | 19 | /// 20 | /// Gets the sources used to obtain configuration values 21 | /// 22 | IList Sources { get; } 23 | 24 | /// 25 | /// Adds a new configuration source. 26 | /// 27 | /// The configuration source to add. 28 | /// The same . 29 | IConfigurationBuilder Add(IConfigurationSource source); 30 | 31 | /// 32 | /// Builds an with keys and values from the set of sources registered in 33 | /// . 34 | /// 35 | /// An with keys and values from the registered sources. 36 | IConfigurationRoot Build(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Config.Abstractions/IConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | using Microsoft.Extensions.Primitives; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// Provides configuration key/values for an application. 11 | /// 12 | public interface IConfigurationProvider 13 | { 14 | /// 15 | /// Tries to get a configuration value for the specified key. 16 | /// 17 | /// The key. 18 | /// The value. 19 | /// True if a value for the specified key was found, otherwise false. 20 | bool TryGet(string key, out string value); 21 | 22 | /// 23 | /// Sets a configuration value for the specified key. 24 | /// 25 | /// The key. 26 | /// The value. 27 | void Set(string key, string value); 28 | 29 | /// 30 | /// Returns a change token if this provider supports change tracking, null otherwise. 31 | /// 32 | /// 33 | IChangeToken GetReloadToken(); 34 | 35 | /// 36 | /// Loads configuration values from the source represented by this . 37 | /// 38 | void Load(); 39 | 40 | /// 41 | /// Returns the immediate descendant configuration keys for a given parent path based on this 42 | /// 's data and the set of keys returned by all the preceding 43 | /// s. 44 | /// 45 | /// The child keys returned by the preceding providers for the same parent path. 46 | /// The parent path. 47 | /// The child keys. 48 | IEnumerable GetChildKeys(IEnumerable earlierKeys, string parentPath); 49 | } 50 | } -------------------------------------------------------------------------------- /src/Config.Abstractions/IConfigurationRoot.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// Represents the root of an hierarchy. 11 | /// 12 | public interface IConfigurationRoot : IConfiguration 13 | { 14 | /// 15 | /// Force the configuration values to be reloaded from the underlying s. 16 | /// 17 | void Reload(); 18 | 19 | /// 20 | /// The s for this configuration. 21 | /// 22 | IEnumerable Providers { get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Config.Abstractions/IConfigurationSection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.Extensions.Configuration 5 | { 6 | /// 7 | /// Represents a section of application configuration values. 8 | /// 9 | public interface IConfigurationSection : IConfiguration 10 | { 11 | /// 12 | /// Gets the key this section occupies in its parent. 13 | /// 14 | string Key { get; } 15 | 16 | /// 17 | /// Gets the full path to this section within the . 18 | /// 19 | string Path { get; } 20 | 21 | /// 22 | /// Gets or sets the section value. 23 | /// 24 | string Value { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Config.Abstractions/IConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.Extensions.Configuration 7 | { 8 | /// 9 | /// Represents a source of configuration key/values for an application. 10 | /// 11 | public interface IConfigurationSource 12 | { 13 | /// 14 | /// Builds the for this source. 15 | /// 16 | /// The . 17 | /// An 18 | IConfigurationProvider Build(IConfigurationBuilder builder); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Config.AzureKeyVault/AzureKeyVaultConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using Microsoft.Azure.KeyVault; 8 | 9 | namespace Microsoft.Extensions.Configuration.AzureKeyVault 10 | { 11 | /// 12 | /// An AzureKeyVault based . 13 | /// 14 | internal class AzureKeyVaultConfigurationProvider : ConfigurationProvider 15 | { 16 | private readonly IKeyVaultClient _client; 17 | private readonly string _vault; 18 | private readonly IKeyVaultSecretManager _manager; 19 | 20 | /// 21 | /// Creates a new instance of . 22 | /// 23 | /// The to use for retrieving values. 24 | /// Azure KeyVault uri. 25 | /// 26 | public AzureKeyVaultConfigurationProvider(IKeyVaultClient client, string vault, IKeyVaultSecretManager manager) 27 | { 28 | if (client == null) 29 | { 30 | throw new ArgumentNullException(nameof(client)); 31 | } 32 | if (vault == null) 33 | { 34 | throw new ArgumentNullException(nameof(vault)); 35 | } 36 | if (manager == null) 37 | { 38 | throw new ArgumentNullException(nameof(manager)); 39 | } 40 | 41 | _client = client; 42 | _vault = vault; 43 | _manager = manager; 44 | } 45 | 46 | public override void Load() => LoadAsync().ConfigureAwait(false).GetAwaiter().GetResult(); 47 | 48 | private async Task LoadAsync() 49 | { 50 | var data = new Dictionary(StringComparer.OrdinalIgnoreCase); 51 | 52 | var secrets = await _client.GetSecretsAsync(_vault).ConfigureAwait(false); 53 | do 54 | { 55 | foreach (var secretItem in secrets) 56 | { 57 | if (!_manager.Load(secretItem) || (secretItem.Attributes?.Enabled != true)) 58 | { 59 | continue; 60 | } 61 | 62 | var value = await _client.GetSecretAsync(secretItem.Id).ConfigureAwait(false); 63 | var key = _manager.GetKey(value); 64 | data.Add(key, value.Value); 65 | } 66 | 67 | secrets = secrets.NextPageLink != null ? 68 | await _client.GetSecretsNextAsync(secrets.NextPageLink).ConfigureAwait(false) : 69 | null; 70 | } while (secrets != null); 71 | 72 | Data = data; 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/Config.AzureKeyVault/AzureKeyVaultConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.Azure.KeyVault; 5 | 6 | namespace Microsoft.Extensions.Configuration.AzureKeyVault 7 | { 8 | /// 9 | /// Represents Azure KeyVault secrets as an . 10 | /// 11 | internal class AzureKeyVaultConfigurationSource : IConfigurationSource 12 | { 13 | /// 14 | /// Gets or sets the to use for retrieving values. 15 | /// 16 | public KeyVaultClient Client { get; set; } 17 | 18 | /// 19 | /// Gets or sets the vault uri. 20 | /// 21 | public string Vault { get; set; } 22 | 23 | /// 24 | /// Gets or sets the instance used to control secret loading. 25 | /// 26 | public IKeyVaultSecretManager Manager { get; set; } 27 | 28 | /// 29 | public IConfigurationProvider Build(IConfigurationBuilder builder) 30 | { 31 | return new AzureKeyVaultConfigurationProvider(new KeyVaultClientWrapper(Client), Vault, Manager); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Config.AzureKeyVault/Config.AzureKeyVault.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.AzureKeyVault 5 | Microsoft.Extensions.Configuration.AzureKeyVault 6 | Azure KeyVault configuration provider implementation for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | $(PackageTags);azure;keyvault 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Config.AzureKeyVault/DefaultKeyVaultSecretManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.Azure.KeyVault; 5 | using Microsoft.Azure.KeyVault.Models; 6 | 7 | namespace Microsoft.Extensions.Configuration.AzureKeyVault 8 | { 9 | /// 10 | /// Default implementation of that loads all secrets 11 | /// and replaces '--' with ':" in key names. 12 | /// 13 | public class DefaultKeyVaultSecretManager : IKeyVaultSecretManager 14 | { 15 | /// 16 | public virtual string GetKey(SecretBundle secret) 17 | { 18 | return secret.SecretIdentifier.Name.Replace("--", ConfigurationPath.KeyDelimiter); 19 | } 20 | 21 | /// 22 | public virtual bool Load(SecretItem secret) 23 | { 24 | return true; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Config.AzureKeyVault/IKeyVaultClient.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Threading.Tasks; 5 | using Microsoft.Azure.KeyVault; 6 | using Microsoft.Azure.KeyVault.Models; 7 | using Microsoft.Rest.Azure; 8 | 9 | namespace Microsoft.Extensions.Configuration.AzureKeyVault 10 | { 11 | /// 12 | /// Client class to perform cryptographic key operations and vault operations 13 | /// against the Key Vault service. 14 | /// Thread safety: This class is thread-safe. 15 | /// 16 | internal interface IKeyVaultClient 17 | { 18 | /// List secrets in the specified vault 19 | /// The URL for the vault containing the secrets. 20 | /// A response message containing a list of secrets in the vault along with a link to the next page of secrets 21 | Task> GetSecretsAsync(string vault); 22 | 23 | /// Gets a secret. 24 | /// The URL for the secret. 25 | /// A response message containing the secret 26 | Task GetSecretAsync(string secretIdentifier); 27 | 28 | /// List the next page of secrets 29 | /// nextLink value from a previous call to GetSecrets or GetSecretsNext 30 | /// A response message containing a list of secrets in the vault along with a link to the next page of secrets 31 | Task> GetSecretsNextAsync(string nextLink); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Config.AzureKeyVault/IKeyVaultSecretManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.Azure.KeyVault.Models; 5 | 6 | namespace Microsoft.Extensions.Configuration.AzureKeyVault 7 | { 8 | /// 9 | /// The instance used to control secret loading. 10 | /// 11 | public interface IKeyVaultSecretManager 12 | { 13 | /// 14 | /// Checks if value should be retrieved. 15 | /// 16 | /// The instance. 17 | /// true is secrets value should be loaded, otherwise false. 18 | bool Load(SecretItem secret); 19 | 20 | /// 21 | /// Maps secret to a configuration key. 22 | /// 23 | /// The instance. 24 | /// Configuration key name to store secret value. 25 | string GetKey(SecretBundle secret); 26 | } 27 | } -------------------------------------------------------------------------------- /src/Config.AzureKeyVault/KeyVaultClientWrapper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Threading.Tasks; 5 | using Microsoft.Azure.KeyVault; 6 | using Microsoft.Azure.KeyVault.Models; 7 | using Microsoft.Rest.Azure; 8 | 9 | namespace Microsoft.Extensions.Configuration.AzureKeyVault 10 | { 11 | /// 12 | internal class KeyVaultClientWrapper : IKeyVaultClient 13 | { 14 | private readonly KeyVaultClient _keyVaultClientImplementation; 15 | 16 | /// 17 | /// Creates a new instance of . 18 | /// 19 | /// The instance to wrap. 20 | public KeyVaultClientWrapper(KeyVaultClient keyVaultClientImplementation) 21 | { 22 | _keyVaultClientImplementation = keyVaultClientImplementation; 23 | } 24 | 25 | /// 26 | public Task> GetSecretsAsync(string vault) 27 | { 28 | return _keyVaultClientImplementation.GetSecretsAsync(vault); 29 | } 30 | 31 | /// 32 | public Task GetSecretAsync(string secretIdentifier) 33 | { 34 | return _keyVaultClientImplementation.GetSecretAsync(secretIdentifier); 35 | } 36 | 37 | /// 38 | public Task> GetSecretsNextAsync(string nextLink) 39 | { 40 | return _keyVaultClientImplementation.GetSecretsNextAsync(nextLink); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Config.AzureKeyVault/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.AzureKeyVault.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] 8 | 9 | -------------------------------------------------------------------------------- /src/Config.Binder/BinderOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.Extensions.Configuration 5 | { 6 | /// 7 | /// Options class used by the . 8 | /// 9 | public class BinderOptions 10 | { 11 | /// 12 | /// When false (the default), the binder will only attempt to set public properties. 13 | /// If true, the binder will attempt to set all non read-only properties. 14 | /// 15 | public bool BindNonPublicProperties { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/Config.Binder/Config.Binder.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Binder 5 | Microsoft.Extensions.Configuration.Binder 6 | Functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Config.Binder/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.Binder.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | 8 | -------------------------------------------------------------------------------- /src/Config.Binder/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Extensions.Configuration.Binder 3 | { 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Resources; 7 | 8 | internal static class Resources 9 | { 10 | private static readonly ResourceManager _resourceManager 11 | = new ResourceManager("Microsoft.Extensions.Configuration.Binder.Resources", typeof(Resources).GetTypeInfo().Assembly); 12 | 13 | /// 14 | /// Cannot create instance of type '{0}' because it is either abstract or an interface. 15 | /// 16 | internal static string Error_CannotActivateAbstractOrInterface 17 | { 18 | get => GetString("Error_CannotActivateAbstractOrInterface"); 19 | } 20 | 21 | /// 22 | /// Cannot create instance of type '{0}' because it is either abstract or an interface. 23 | /// 24 | internal static string FormatError_CannotActivateAbstractOrInterface(object p0) 25 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_CannotActivateAbstractOrInterface"), p0); 26 | 27 | /// 28 | /// Failed to convert '{0}' to type '{1}'. 29 | /// 30 | internal static string Error_FailedBinding 31 | { 32 | get => GetString("Error_FailedBinding"); 33 | } 34 | 35 | /// 36 | /// Failed to convert '{0}' to type '{1}'. 37 | /// 38 | internal static string FormatError_FailedBinding(object p0, object p1) 39 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_FailedBinding"), p0, p1); 40 | 41 | /// 42 | /// Failed to create instance of type '{0}'. 43 | /// 44 | internal static string Error_FailedToActivate 45 | { 46 | get => GetString("Error_FailedToActivate"); 47 | } 48 | 49 | /// 50 | /// Failed to create instance of type '{0}'. 51 | /// 52 | internal static string FormatError_FailedToActivate(object p0) 53 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_FailedToActivate"), p0); 54 | 55 | /// 56 | /// Cannot create instance of type '{0}' because it is missing a public parameterless constructor. 57 | /// 58 | internal static string Error_MissingParameterlessConstructor 59 | { 60 | get => GetString("Error_MissingParameterlessConstructor"); 61 | } 62 | 63 | /// 64 | /// Cannot create instance of type '{0}' because it is missing a public parameterless constructor. 65 | /// 66 | internal static string FormatError_MissingParameterlessConstructor(object p0) 67 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_MissingParameterlessConstructor"), p0); 68 | 69 | /// 70 | /// Cannot create instance of type '{0}' because multidimensional arrays are not supported. 71 | /// 72 | internal static string Error_UnsupportedMultidimensionalArray 73 | { 74 | get => GetString("Error_UnsupportedMultidimensionalArray"); 75 | } 76 | 77 | /// 78 | /// Cannot create instance of type '{0}' because multidimensional arrays are not supported. 79 | /// 80 | internal static string FormatError_UnsupportedMultidimensionalArray(object p0) 81 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_UnsupportedMultidimensionalArray"), p0); 82 | 83 | private static string GetString(string name, params string[] formatterNames) 84 | { 85 | var value = _resourceManager.GetString(name); 86 | 87 | System.Diagnostics.Debug.Assert(value != null); 88 | 89 | if (formatterNames != null) 90 | { 91 | for (var i = 0; i < formatterNames.Length; i++) 92 | { 93 | value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); 94 | } 95 | } 96 | 97 | return value; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Config.CommandLine/CommandLineConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.Extensions.Configuration.CommandLine; 7 | 8 | namespace Microsoft.Extensions.Configuration 9 | { 10 | /// 11 | /// Extension methods for registering with . 12 | /// 13 | public static class CommandLineConfigurationExtensions 14 | { 15 | /// 16 | /// Adds an that reads configuration values from the command line. 17 | /// 18 | /// The to add to. 19 | /// The command line args. 20 | /// The . 21 | public static IConfigurationBuilder AddCommandLine(this IConfigurationBuilder configurationBuilder, string[] args) 22 | { 23 | return configurationBuilder.AddCommandLine(args, switchMappings: null); 24 | } 25 | 26 | /// 27 | /// Adds an that reads configuration values from the command line using the specified switch mappings. 28 | /// 29 | /// The to add to. 30 | /// The command line args. 31 | /// The switch mappings. 32 | /// The . 33 | public static IConfigurationBuilder AddCommandLine( 34 | this IConfigurationBuilder configurationBuilder, 35 | string[] args, 36 | IDictionary switchMappings) 37 | { 38 | configurationBuilder.Add(new CommandLineConfigurationSource { Args = args, SwitchMappings = switchMappings }); 39 | return configurationBuilder; 40 | } 41 | 42 | /// 43 | /// Adds an that reads configuration values from the command line. 44 | /// 45 | /// The to add to. 46 | /// Configures the source. 47 | /// The . 48 | public static IConfigurationBuilder AddCommandLine(this IConfigurationBuilder builder, Action configureSource) 49 | => builder.Add(configureSource); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Config.CommandLine/CommandLineConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.Extensions.Configuration.CommandLine 7 | { 8 | /// 9 | /// Represents command line arguments as an . 10 | /// 11 | public class CommandLineConfigurationSource : IConfigurationSource 12 | { 13 | /// 14 | /// Gets or sets the switch mappings. 15 | /// 16 | public IDictionary SwitchMappings { get; set; } 17 | 18 | /// 19 | /// Gets or sets the command line args. 20 | /// 21 | public IEnumerable Args { get; set; } 22 | 23 | /// 24 | /// Builds the for this source. 25 | /// 26 | /// The . 27 | /// A 28 | public IConfigurationProvider Build(IConfigurationBuilder builder) 29 | { 30 | return new CommandLineConfigurationProvider(Args, SwitchMappings); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Config.CommandLine/Config.CommandLine.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.CommandLine 5 | Microsoft.Extensions.Configuration.CommandLine 6 | Command line configuration provider implementation for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | $(PackageTags);commandline 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Config.CommandLine/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.CommandLine.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | 8 | -------------------------------------------------------------------------------- /src/Config.CommandLine/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Extensions.Configuration.CommandLine 3 | { 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Resources; 7 | 8 | internal static class Resources 9 | { 10 | private static readonly ResourceManager _resourceManager 11 | = new ResourceManager("Microsoft.Extensions.Configuration.CommandLine.Resources", typeof(Resources).GetTypeInfo().Assembly); 12 | 13 | /// 14 | /// Keys in switch mappings are case-insensitive. A duplicated key '{0}' was found. 15 | /// 16 | internal static string Error_DuplicatedKeyInSwitchMappings 17 | { 18 | get => GetString("Error_DuplicatedKeyInSwitchMappings"); 19 | } 20 | 21 | /// 22 | /// Keys in switch mappings are case-insensitive. A duplicated key '{0}' was found. 23 | /// 24 | internal static string FormatError_DuplicatedKeyInSwitchMappings(object p0) 25 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_DuplicatedKeyInSwitchMappings"), p0); 26 | 27 | /// 28 | /// The switch mappings contain an invalid switch '{0}'. 29 | /// 30 | internal static string Error_InvalidSwitchMapping 31 | { 32 | get => GetString("Error_InvalidSwitchMapping"); 33 | } 34 | 35 | /// 36 | /// The switch mappings contain an invalid switch '{0}'. 37 | /// 38 | internal static string FormatError_InvalidSwitchMapping(object p0) 39 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_InvalidSwitchMapping"), p0); 40 | 41 | /// 42 | /// The short switch '{0}' is not defined in the switch mappings. 43 | /// 44 | internal static string Error_ShortSwitchNotDefined 45 | { 46 | get => GetString("Error_ShortSwitchNotDefined"); 47 | } 48 | 49 | /// 50 | /// The short switch '{0}' is not defined in the switch mappings. 51 | /// 52 | internal static string FormatError_ShortSwitchNotDefined(object p0) 53 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_ShortSwitchNotDefined"), p0); 54 | 55 | private static string GetString(string name, params string[] formatterNames) 56 | { 57 | var value = _resourceManager.GetString(name); 58 | 59 | System.Diagnostics.Debug.Assert(value != null); 60 | 61 | if (formatterNames != null) 62 | { 63 | for (var i = 0; i < formatterNames.Length; i++) 64 | { 65 | value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); 66 | } 67 | } 68 | 69 | return value; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Config.EnvironmentVariables/Config.EnvironmentVariables.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.EnvironmentVariables 5 | Microsoft.Extensions.Configuration.EnvironmentVariables 6 | Environment variables configuration provider implementation for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | $(PackageTags);envvar;environmentvariable 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Config.EnvironmentVariables/EnvironmentVariablesConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace Microsoft.Extensions.Configuration.EnvironmentVariables 10 | { 11 | /// 12 | /// An environment variable based . 13 | /// 14 | public class EnvironmentVariablesConfigurationProvider : ConfigurationProvider 15 | { 16 | private const string MySqlServerPrefix = "MYSQLCONNSTR_"; 17 | private const string SqlAzureServerPrefix = "SQLAZURECONNSTR_"; 18 | private const string SqlServerPrefix = "SQLCONNSTR_"; 19 | private const string CustomPrefix = "CUSTOMCONNSTR_"; 20 | 21 | private const string ConnStrKeyFormat = "ConnectionStrings:{0}"; 22 | private const string ProviderKeyFormat = "ConnectionStrings:{0}_ProviderName"; 23 | 24 | private readonly string _prefix; 25 | 26 | /// 27 | /// Initializes a new instance. 28 | /// 29 | public EnvironmentVariablesConfigurationProvider() : this(string.Empty) 30 | { } 31 | 32 | /// 33 | /// Initializes a new instance with the specified prefix. 34 | /// 35 | /// A prefix used to filter the environment variables. 36 | public EnvironmentVariablesConfigurationProvider(string prefix) 37 | { 38 | _prefix = prefix ?? string.Empty; 39 | } 40 | 41 | /// 42 | /// Loads the environment variables. 43 | /// 44 | public override void Load() 45 | { 46 | Load(Environment.GetEnvironmentVariables()); 47 | } 48 | 49 | internal void Load(IDictionary envVariables) 50 | { 51 | Data = new Dictionary(StringComparer.OrdinalIgnoreCase); 52 | 53 | var filteredEnvVariables = envVariables 54 | .Cast() 55 | .SelectMany(AzureEnvToAppEnv) 56 | .Where(entry => ((string)entry.Key).StartsWith(_prefix, StringComparison.OrdinalIgnoreCase)); 57 | 58 | foreach (var envVariable in filteredEnvVariables) 59 | { 60 | var key = ((string)envVariable.Key).Substring(_prefix.Length); 61 | Data[key] = (string)envVariable.Value; 62 | } 63 | } 64 | 65 | private static string NormalizeKey(string key) 66 | { 67 | return key.Replace("__", ConfigurationPath.KeyDelimiter); 68 | } 69 | 70 | private static IEnumerable AzureEnvToAppEnv(DictionaryEntry entry) 71 | { 72 | var key = (string)entry.Key; 73 | var prefix = string.Empty; 74 | var provider = string.Empty; 75 | 76 | if (key.StartsWith(MySqlServerPrefix, StringComparison.OrdinalIgnoreCase)) 77 | { 78 | prefix = MySqlServerPrefix; 79 | provider = "MySql.Data.MySqlClient"; 80 | } 81 | else if (key.StartsWith(SqlAzureServerPrefix, StringComparison.OrdinalIgnoreCase)) 82 | { 83 | prefix = SqlAzureServerPrefix; 84 | provider = "System.Data.SqlClient"; 85 | } 86 | else if (key.StartsWith(SqlServerPrefix, StringComparison.OrdinalIgnoreCase)) 87 | { 88 | prefix = SqlServerPrefix; 89 | provider = "System.Data.SqlClient"; 90 | } 91 | else if (key.StartsWith(CustomPrefix, StringComparison.OrdinalIgnoreCase)) 92 | { 93 | prefix = CustomPrefix; 94 | } 95 | else 96 | { 97 | entry.Key = NormalizeKey(key); 98 | yield return entry; 99 | yield break; 100 | } 101 | 102 | // Return the key-value pair for connection string 103 | yield return new DictionaryEntry( 104 | string.Format(ConnStrKeyFormat, NormalizeKey(key.Substring(prefix.Length))), 105 | entry.Value); 106 | 107 | if (!string.IsNullOrEmpty(provider)) 108 | { 109 | // Return the key-value pair for provider name 110 | yield return new DictionaryEntry( 111 | string.Format(ProviderKeyFormat, NormalizeKey(key.Substring(prefix.Length))), 112 | provider); 113 | } 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Config.EnvironmentVariables/EnvironmentVariablesConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.Extensions.Configuration.EnvironmentVariables 5 | { 6 | /// 7 | /// Represents environment variables as an . 8 | /// 9 | public class EnvironmentVariablesConfigurationSource : IConfigurationSource 10 | { 11 | /// 12 | /// A prefix used to filter environment variables. 13 | /// 14 | public string Prefix { get; set; } 15 | 16 | /// 17 | /// Builds the for this source. 18 | /// 19 | /// The . 20 | /// A 21 | public IConfigurationProvider Build(IConfigurationBuilder builder) 22 | { 23 | return new EnvironmentVariablesConfigurationProvider(Prefix); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Config.EnvironmentVariables/EnvironmentVariablesExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.Extensions.Configuration.EnvironmentVariables; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// Extension methods for registering with . 11 | /// 12 | public static class EnvironmentVariablesExtensions 13 | { 14 | /// 15 | /// Adds an that reads configuration values from environment variables. 16 | /// 17 | /// The to add to. 18 | /// The . 19 | public static IConfigurationBuilder AddEnvironmentVariables(this IConfigurationBuilder configurationBuilder) 20 | { 21 | configurationBuilder.Add(new EnvironmentVariablesConfigurationSource()); 22 | return configurationBuilder; 23 | } 24 | 25 | /// 26 | /// Adds an that reads configuration values from environment variables 27 | /// with a specified prefix. 28 | /// 29 | /// The to add to. 30 | /// The prefix that environment variable names must start with. The prefix will be removed from the environment variable names. 31 | /// The . 32 | public static IConfigurationBuilder AddEnvironmentVariables( 33 | this IConfigurationBuilder configurationBuilder, 34 | string prefix) 35 | { 36 | configurationBuilder.Add(new EnvironmentVariablesConfigurationSource { Prefix = prefix }); 37 | return configurationBuilder; 38 | } 39 | 40 | /// 41 | /// Adds an that reads configuration values from environment variables. 42 | /// 43 | /// The to add to. 44 | /// Configures the source. 45 | /// The . 46 | public static IConfigurationBuilder AddEnvironmentVariables(this IConfigurationBuilder builder, Action configureSource) 47 | => builder.Add(configureSource); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Config.EnvironmentVariables/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.EnvironmentVariables.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | 8 | -------------------------------------------------------------------------------- /src/Config.FileExtensions/Config.FileExtensions.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.FileExtensions 5 | Microsoft.Extensions.Configuration.FileExtensions 6 | Extension methods for configuring file-based configuration providers for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Config.FileExtensions/FileConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.Extensions.FileProviders; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// Extension methods for . 11 | /// 12 | public static class FileConfigurationExtensions 13 | { 14 | private static string FileProviderKey = "FileProvider"; 15 | private static string FileLoadExceptionHandlerKey = "FileLoadExceptionHandler"; 16 | 17 | /// 18 | /// Sets the default to be used for file-based providers. 19 | /// 20 | /// The to add to. 21 | /// The default file provider instance. 22 | /// The . 23 | public static IConfigurationBuilder SetFileProvider(this IConfigurationBuilder builder, IFileProvider fileProvider) 24 | { 25 | if (builder == null) 26 | { 27 | throw new ArgumentNullException(nameof(builder)); 28 | } 29 | 30 | builder.Properties[FileProviderKey] = fileProvider ?? throw new ArgumentNullException(nameof(fileProvider)); 31 | return builder; 32 | } 33 | 34 | /// 35 | /// Gets the default to be used for file-based providers. 36 | /// 37 | /// The . 38 | /// The . 39 | public static IFileProvider GetFileProvider(this IConfigurationBuilder builder) 40 | { 41 | if (builder == null) 42 | { 43 | throw new ArgumentNullException(nameof(builder)); 44 | } 45 | 46 | if (builder.Properties.TryGetValue(FileProviderKey, out object provider)) 47 | { 48 | return builder.Properties[FileProviderKey] as IFileProvider; 49 | } 50 | 51 | return new PhysicalFileProvider(AppContext.BaseDirectory ?? string.Empty); 52 | } 53 | 54 | /// 55 | /// Sets the FileProvider for file-based providers to a PhysicalFileProvider with the base path. 56 | /// 57 | /// The to add to. 58 | /// The absolute path of file-based providers. 59 | /// The . 60 | public static IConfigurationBuilder SetBasePath(this IConfigurationBuilder builder, string basePath) 61 | { 62 | if (builder == null) 63 | { 64 | throw new ArgumentNullException(nameof(builder)); 65 | } 66 | 67 | if (basePath == null) 68 | { 69 | throw new ArgumentNullException(nameof(basePath)); 70 | } 71 | 72 | return builder.SetFileProvider(new PhysicalFileProvider(basePath)); 73 | } 74 | 75 | /// 76 | /// Sets a default action to be invoked for file-based providers when an error occurs. 77 | /// 78 | /// The to add to. 79 | /// The Action to be invoked on a file load exception. 80 | /// The . 81 | public static IConfigurationBuilder SetFileLoadExceptionHandler(this IConfigurationBuilder builder, Action handler) 82 | { 83 | if (builder == null) 84 | { 85 | throw new ArgumentNullException(nameof(builder)); 86 | } 87 | 88 | builder.Properties[FileLoadExceptionHandlerKey] = handler; 89 | return builder; 90 | } 91 | 92 | /// 93 | /// Gets the default to be used for file-based providers. 94 | /// 95 | /// The . 96 | /// The . 97 | public static Action GetFileLoadExceptionHandler(this IConfigurationBuilder builder) 98 | { 99 | if (builder == null) 100 | { 101 | throw new ArgumentNullException(nameof(builder)); 102 | } 103 | 104 | if (builder.Properties.TryGetValue(FileLoadExceptionHandlerKey, out object handler)) 105 | { 106 | return builder.Properties[FileLoadExceptionHandlerKey] as Action; 107 | } 108 | return null; 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /src/Config.FileExtensions/FileConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Text; 8 | using System.Threading; 9 | using Microsoft.Extensions.Primitives; 10 | 11 | namespace Microsoft.Extensions.Configuration 12 | { 13 | /// 14 | /// Base class for file based . 15 | /// 16 | public abstract class FileConfigurationProvider : ConfigurationProvider 17 | { 18 | /// 19 | /// Initializes a new instance with the specified source. 20 | /// 21 | /// The source settings. 22 | public FileConfigurationProvider(FileConfigurationSource source) 23 | { 24 | if (source == null) 25 | { 26 | throw new ArgumentNullException(nameof(source)); 27 | } 28 | Source = source; 29 | 30 | if (Source.ReloadOnChange && Source.FileProvider != null) 31 | { 32 | ChangeToken.OnChange( 33 | () => Source.FileProvider.Watch(Source.Path), 34 | () => { 35 | Thread.Sleep(Source.ReloadDelay); 36 | Load(reload: true); 37 | }); 38 | } 39 | } 40 | 41 | /// 42 | /// The source settings for this provider. 43 | /// 44 | public FileConfigurationSource Source { get; } 45 | 46 | private void Load(bool reload) 47 | { 48 | var file = Source.FileProvider?.GetFileInfo(Source.Path); 49 | if (file == null || !file.Exists) 50 | { 51 | if (Source.Optional || reload) // Always optional on reload 52 | { 53 | Data = new Dictionary(StringComparer.OrdinalIgnoreCase); 54 | } 55 | else 56 | { 57 | var error = new StringBuilder($"The configuration file '{Source.Path}' was not found and is not optional."); 58 | if (!string.IsNullOrEmpty(file?.PhysicalPath)) 59 | { 60 | error.Append($" The physical path is '{file.PhysicalPath}'."); 61 | } 62 | throw new FileNotFoundException(error.ToString()); 63 | } 64 | } 65 | else 66 | { 67 | // Always create new Data on reload to drop old keys 68 | if (reload) 69 | { 70 | Data = new Dictionary(StringComparer.OrdinalIgnoreCase); 71 | } 72 | using (var stream = file.CreateReadStream()) 73 | { 74 | try 75 | { 76 | Load(stream); 77 | } 78 | catch (Exception e) 79 | { 80 | bool ignoreException = false; 81 | if (Source.OnLoadException != null) 82 | { 83 | var exceptionContext = new FileLoadExceptionContext 84 | { 85 | Provider = this, 86 | Exception = e 87 | }; 88 | Source.OnLoadException.Invoke(exceptionContext); 89 | ignoreException = exceptionContext.Ignore; 90 | } 91 | if (!ignoreException) 92 | { 93 | throw e; 94 | } 95 | } 96 | } 97 | } 98 | // REVIEW: Should we raise this in the base as well / instead? 99 | OnReload(); 100 | } 101 | 102 | /// 103 | /// Loads the contents of the file at . 104 | /// 105 | /// If Optional is false on the source and a 106 | /// file does not exist at specified Path. 107 | public override void Load() 108 | { 109 | Load(reload: false); 110 | } 111 | 112 | /// 113 | /// Loads this provider's data from a stream. 114 | /// 115 | /// The stream to read. 116 | public abstract void Load(Stream stream); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/Config.FileExtensions/FileConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using Microsoft.Extensions.FileProviders; 7 | 8 | namespace Microsoft.Extensions.Configuration 9 | { 10 | /// 11 | /// Represents a base class for file based . 12 | /// 13 | public abstract class FileConfigurationSource : IConfigurationSource 14 | { 15 | /// 16 | /// Used to access the contents of the file. 17 | /// 18 | public IFileProvider FileProvider { get; set; } 19 | 20 | /// 21 | /// The path to the file. 22 | /// 23 | public string Path { get; set; } 24 | 25 | /// 26 | /// Determines if loading the file is optional. 27 | /// 28 | public bool Optional { get; set; } 29 | 30 | /// 31 | /// Determines whether the source will be loaded if the underlying file changes. 32 | /// 33 | public bool ReloadOnChange { get; set; } 34 | 35 | /// 36 | /// Number of milliseconds that reload will wait before calling Load. This helps 37 | /// avoid triggering reload before a file is completely written. Default is 250. 38 | /// 39 | public int ReloadDelay { get; set; } = 250; 40 | 41 | /// 42 | /// Will be called if an uncaught exception occurs in FileConfigurationProvider.Load. 43 | /// 44 | public Action OnLoadException { get; set; } 45 | 46 | /// 47 | /// Builds the for this source. 48 | /// 49 | /// The . 50 | /// A 51 | public abstract IConfigurationProvider Build(IConfigurationBuilder builder); 52 | 53 | /// 54 | /// Called to use any default settings on the builder like the FileProvider or FileLoadExceptionHandler. 55 | /// 56 | /// The . 57 | public void EnsureDefaults(IConfigurationBuilder builder) 58 | { 59 | FileProvider = FileProvider ?? builder.GetFileProvider(); 60 | OnLoadException = OnLoadException ?? builder.GetFileLoadExceptionHandler(); 61 | } 62 | 63 | /// 64 | /// If no file provider has been set, for absolute Path, this will creates a physical file provider 65 | /// for the nearest existing directory. 66 | /// 67 | public void ResolveFileProvider() 68 | { 69 | if (FileProvider == null && 70 | !string.IsNullOrEmpty(Path) && 71 | System.IO.Path.IsPathRooted(Path)) 72 | { 73 | var directory = System.IO.Path.GetDirectoryName(Path); 74 | var pathToFile = System.IO.Path.GetFileName(Path); 75 | while (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) 76 | { 77 | pathToFile = System.IO.Path.Combine(System.IO.Path.GetFileName(directory), pathToFile); 78 | directory = System.IO.Path.GetDirectoryName(directory); 79 | } 80 | if (Directory.Exists(directory)) 81 | { 82 | FileProvider = new PhysicalFileProvider(directory); 83 | Path = pathToFile; 84 | } 85 | } 86 | } 87 | 88 | } 89 | } -------------------------------------------------------------------------------- /src/Config.FileExtensions/FileLoadExceptionContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Extensions.Configuration 7 | { 8 | /// 9 | /// Contains information about a file load exception. 10 | /// 11 | public class FileLoadExceptionContext 12 | { 13 | /// 14 | /// The that caused the exception. 15 | /// 16 | public FileConfigurationProvider Provider { get; set; } 17 | 18 | /// 19 | /// The exception that occured in Load. 20 | /// 21 | public Exception Exception { get; set; } 22 | 23 | /// 24 | /// If true, the exception will not be rethrown. 25 | /// 26 | public bool Ignore { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Config.FileExtensions/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.FileExtensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | 8 | -------------------------------------------------------------------------------- /src/Config.FileExtensions/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Extensions.Configuration.FileExtensions 3 | { 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Resources; 7 | 8 | internal static class Resources 9 | { 10 | private static readonly ResourceManager _resourceManager 11 | = new ResourceManager("Microsoft.Extensions.Configuration.FileExtensions.Resources", typeof(Resources).GetTypeInfo().Assembly); 12 | 13 | /// 14 | /// The expected physical path was '{0}'. 15 | /// 16 | internal static string Error_ExpectedPhysicalPath 17 | { 18 | get => GetString("Error_ExpectedPhysicalPath"); 19 | } 20 | 21 | /// 22 | /// The expected physical path was '{0}'. 23 | /// 24 | internal static string FormatError_ExpectedPhysicalPath(object p0) 25 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_ExpectedPhysicalPath"), p0); 26 | 27 | /// 28 | /// The configuration file '{0}' was not found and is not optional. 29 | /// 30 | internal static string Error_FileNotFound 31 | { 32 | get => GetString("Error_FileNotFound"); 33 | } 34 | 35 | /// 36 | /// The configuration file '{0}' was not found and is not optional. 37 | /// 38 | internal static string FormatError_FileNotFound(object p0) 39 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_FileNotFound"), p0); 40 | 41 | private static string GetString(string name, params string[] formatterNames) 42 | { 43 | var value = _resourceManager.GetString(name); 44 | 45 | System.Diagnostics.Debug.Assert(value != null); 46 | 47 | if (formatterNames != null) 48 | { 49 | for (var i = 0; i < formatterNames.Length; i++) 50 | { 51 | value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); 52 | } 53 | } 54 | 55 | return value; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Config.Ini/Config.Ini.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Ini 5 | Microsoft.Extensions.Configuration.Ini 6 | INI configuration provider implementation for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | $(PackageTags);ini 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Config.Ini/IniConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | 8 | namespace Microsoft.Extensions.Configuration.Ini 9 | { 10 | /// 11 | /// An INI file based . 12 | /// Files are simple line structures (INI Files on Wikipedia) 13 | /// 14 | /// 15 | /// [Section:Header] 16 | /// key1=value1 17 | /// key2 = " value2 " 18 | /// ; comment 19 | /// # comment 20 | /// / comment 21 | /// 22 | public class IniConfigurationProvider : FileConfigurationProvider 23 | { 24 | /// 25 | /// Initializes a new instance with the specified source. 26 | /// 27 | /// The source settings. 28 | public IniConfigurationProvider(IniConfigurationSource source) : base(source) { } 29 | 30 | /// 31 | /// Loads the INI data from a stream. 32 | /// 33 | /// The stream to read. 34 | public override void Load(Stream stream) 35 | { 36 | var data = new Dictionary(StringComparer.OrdinalIgnoreCase); 37 | 38 | using (var reader = new StreamReader(stream)) 39 | { 40 | var sectionPrefix = string.Empty; 41 | 42 | while (reader.Peek() != -1) 43 | { 44 | var rawLine = reader.ReadLine(); 45 | var line = rawLine.Trim(); 46 | 47 | // Ignore blank lines 48 | if (string.IsNullOrWhiteSpace(line)) 49 | { 50 | continue; 51 | } 52 | // Ignore comments 53 | if (line[0] == ';' || line[0] == '#' || line[0] == '/') 54 | { 55 | continue; 56 | } 57 | // [Section:header] 58 | if (line[0] == '[' && line[line.Length - 1] == ']') 59 | { 60 | // remove the brackets 61 | sectionPrefix = line.Substring(1, line.Length - 2) + ConfigurationPath.KeyDelimiter; 62 | continue; 63 | } 64 | 65 | // key = value OR "value" 66 | int separator = line.IndexOf('='); 67 | if (separator < 0) 68 | { 69 | throw new FormatException(Resources.FormatError_UnrecognizedLineFormat(rawLine)); 70 | } 71 | 72 | string key = sectionPrefix + line.Substring(0, separator).Trim(); 73 | string value = line.Substring(separator + 1).Trim(); 74 | 75 | // Remove quotes 76 | if (value.Length > 1 && value[0] == '"' && value[value.Length - 1] == '"') 77 | { 78 | value = value.Substring(1, value.Length - 2); 79 | } 80 | 81 | if (data.ContainsKey(key)) 82 | { 83 | throw new FormatException(Resources.FormatError_KeyIsDuplicated(key)); 84 | } 85 | 86 | data[key] = value; 87 | } 88 | } 89 | 90 | Data = data; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Config.Ini/IniConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.Extensions.Configuration.Ini 5 | { 6 | /// 7 | /// Represents an INI file as an . 8 | /// Files are simple line structures (INI Files on Wikipedia) 9 | /// 10 | /// 11 | /// [Section:Header] 12 | /// key1=value1 13 | /// key2 = " value2 " 14 | /// ; comment 15 | /// # comment 16 | /// / comment 17 | /// 18 | public class IniConfigurationSource : FileConfigurationSource 19 | { 20 | /// 21 | /// Builds the for this source. 22 | /// 23 | /// The . 24 | /// An 25 | public override IConfigurationProvider Build(IConfigurationBuilder builder) 26 | { 27 | EnsureDefaults(builder); 28 | return new IniConfigurationProvider(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Config.Ini/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.Ini.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | 8 | -------------------------------------------------------------------------------- /src/Config.Ini/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Extensions.Configuration.Ini 3 | { 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Resources; 7 | 8 | internal static class Resources 9 | { 10 | private static readonly ResourceManager _resourceManager 11 | = new ResourceManager("Microsoft.Extensions.Configuration.Ini.Resources", typeof(Resources).GetTypeInfo().Assembly); 12 | 13 | /// 14 | /// File path must be a non-empty string. 15 | /// 16 | internal static string Error_InvalidFilePath 17 | { 18 | get => GetString("Error_InvalidFilePath"); 19 | } 20 | 21 | /// 22 | /// File path must be a non-empty string. 23 | /// 24 | internal static string FormatError_InvalidFilePath() 25 | => GetString("Error_InvalidFilePath"); 26 | 27 | /// 28 | /// A duplicate key '{0}' was found. 29 | /// 30 | internal static string Error_KeyIsDuplicated 31 | { 32 | get => GetString("Error_KeyIsDuplicated"); 33 | } 34 | 35 | /// 36 | /// A duplicate key '{0}' was found. 37 | /// 38 | internal static string FormatError_KeyIsDuplicated(object p0) 39 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_KeyIsDuplicated"), p0); 40 | 41 | /// 42 | /// Unrecognized line format: '{0}'. 43 | /// 44 | internal static string Error_UnrecognizedLineFormat 45 | { 46 | get => GetString("Error_UnrecognizedLineFormat"); 47 | } 48 | 49 | /// 50 | /// Unrecognized line format: '{0}'. 51 | /// 52 | internal static string FormatError_UnrecognizedLineFormat(object p0) 53 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_UnrecognizedLineFormat"), p0); 54 | 55 | private static string GetString(string name, params string[] formatterNames) 56 | { 57 | var value = _resourceManager.GetString(name); 58 | 59 | System.Diagnostics.Debug.Assert(value != null); 60 | 61 | if (formatterNames != null) 62 | { 63 | for (var i = 0; i < formatterNames.Length; i++) 64 | { 65 | value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); 66 | } 67 | } 68 | 69 | return value; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Config.Json/Config.Json.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Json 5 | Microsoft.Extensions.Configuration.Json 6 | JSON configuration provider implementation for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | $(PackageTags);json 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Config.Json/JsonConfigurationFileParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Globalization; 7 | using System.IO; 8 | using System.Linq; 9 | using Newtonsoft.Json; 10 | using Newtonsoft.Json.Linq; 11 | 12 | namespace Microsoft.Extensions.Configuration.Json 13 | { 14 | internal class JsonConfigurationFileParser 15 | { 16 | private JsonConfigurationFileParser() { } 17 | 18 | private readonly IDictionary _data = new SortedDictionary(StringComparer.OrdinalIgnoreCase); 19 | private readonly Stack _context = new Stack(); 20 | private string _currentPath; 21 | 22 | private JsonTextReader _reader; 23 | 24 | public static IDictionary Parse(Stream input) 25 | => new JsonConfigurationFileParser().ParseStream(input); 26 | 27 | private IDictionary ParseStream(Stream input) 28 | { 29 | _data.Clear(); 30 | _reader = new JsonTextReader(new StreamReader(input)); 31 | _reader.DateParseHandling = DateParseHandling.None; 32 | 33 | var jsonConfig = JObject.Load(_reader); 34 | 35 | VisitJObject(jsonConfig); 36 | 37 | return _data; 38 | } 39 | 40 | private void VisitJObject(JObject jObject) 41 | { 42 | foreach (var property in jObject.Properties()) 43 | { 44 | EnterContext(property.Name); 45 | VisitProperty(property); 46 | ExitContext(); 47 | } 48 | } 49 | 50 | private void VisitProperty(JProperty property) 51 | { 52 | VisitToken(property.Value); 53 | } 54 | 55 | private void VisitToken(JToken token) 56 | { 57 | switch (token.Type) 58 | { 59 | case JTokenType.Object: 60 | VisitJObject(token.Value()); 61 | break; 62 | 63 | case JTokenType.Array: 64 | VisitArray(token.Value()); 65 | break; 66 | 67 | case JTokenType.Integer: 68 | case JTokenType.Float: 69 | case JTokenType.String: 70 | case JTokenType.Boolean: 71 | case JTokenType.Bytes: 72 | case JTokenType.Raw: 73 | case JTokenType.Null: 74 | VisitPrimitive(token.Value()); 75 | break; 76 | 77 | default: 78 | throw new FormatException(Resources.FormatError_UnsupportedJSONToken( 79 | _reader.TokenType, 80 | _reader.Path, 81 | _reader.LineNumber, 82 | _reader.LinePosition)); 83 | } 84 | } 85 | 86 | private void VisitArray(JArray array) 87 | { 88 | for (int index = 0; index < array.Count; index++) 89 | { 90 | EnterContext(index.ToString()); 91 | VisitToken(array[index]); 92 | ExitContext(); 93 | } 94 | } 95 | 96 | private void VisitPrimitive(JValue data) 97 | { 98 | var key = _currentPath; 99 | 100 | if (_data.ContainsKey(key)) 101 | { 102 | throw new FormatException(Resources.FormatError_KeyIsDuplicated(key)); 103 | } 104 | _data[key] = data.ToString(CultureInfo.InvariantCulture); 105 | } 106 | 107 | private void EnterContext(string context) 108 | { 109 | _context.Push(context); 110 | _currentPath = ConfigurationPath.Combine(_context.Reverse()); 111 | } 112 | 113 | private void ExitContext() 114 | { 115 | _context.Pop(); 116 | _currentPath = ConfigurationPath.Combine(_context.Reverse()); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Config.Json/JsonConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using Newtonsoft.Json; 9 | 10 | namespace Microsoft.Extensions.Configuration.Json 11 | { 12 | /// 13 | /// A JSON file based . 14 | /// 15 | public class JsonConfigurationProvider : FileConfigurationProvider 16 | { 17 | /// 18 | /// Initializes a new instance with the specified source. 19 | /// 20 | /// The source settings. 21 | public JsonConfigurationProvider(JsonConfigurationSource source) : base(source) { } 22 | 23 | /// 24 | /// Loads the JSON data from a stream. 25 | /// 26 | /// The stream to read. 27 | public override void Load(Stream stream) 28 | { 29 | try 30 | { 31 | Data = JsonConfigurationFileParser.Parse(stream); 32 | } 33 | catch (JsonReaderException e) 34 | { 35 | string errorLine = string.Empty; 36 | if (stream.CanSeek) 37 | { 38 | stream.Seek(0, SeekOrigin.Begin); 39 | 40 | IEnumerable fileContent; 41 | using (var streamReader = new StreamReader(stream)) 42 | { 43 | fileContent = ReadLines(streamReader); 44 | errorLine = RetrieveErrorContext(e, fileContent); 45 | } 46 | } 47 | 48 | throw new FormatException(Resources.FormatError_JSONParseError(e.LineNumber, errorLine), e); 49 | } 50 | } 51 | 52 | private static string RetrieveErrorContext(JsonReaderException e, IEnumerable fileContent) 53 | { 54 | string errorLine = null; 55 | if (e.LineNumber >= 2) 56 | { 57 | var errorContext = fileContent.Skip(e.LineNumber - 2).Take(2).ToList(); 58 | // Handle situations when the line number reported is out of bounds 59 | if (errorContext.Count() >= 2) 60 | { 61 | errorLine = errorContext[0].Trim() + Environment.NewLine + errorContext[1].Trim(); 62 | } 63 | } 64 | if (string.IsNullOrEmpty(errorLine)) 65 | { 66 | var possibleLineContent = fileContent.Skip(e.LineNumber - 1).FirstOrDefault(); 67 | errorLine = possibleLineContent ?? string.Empty; 68 | } 69 | return errorLine; 70 | } 71 | 72 | private static IEnumerable ReadLines(StreamReader streamReader) 73 | { 74 | string line; 75 | do 76 | { 77 | line = streamReader.ReadLine(); 78 | yield return line; 79 | } while (line != null); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Config.Json/JsonConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Extensions.Configuration.Json 7 | { 8 | /// 9 | /// Represents a JSON file as an . 10 | /// 11 | public class JsonConfigurationSource : FileConfigurationSource 12 | { 13 | /// 14 | /// Builds the for this source. 15 | /// 16 | /// The . 17 | /// A 18 | public override IConfigurationProvider Build(IConfigurationBuilder builder) 19 | { 20 | EnsureDefaults(builder); 21 | return new JsonConfigurationProvider(this); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Config.Json/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.Json.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | 8 | -------------------------------------------------------------------------------- /src/Config.Json/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Extensions.Configuration.Json 3 | { 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Resources; 7 | 8 | internal static class Resources 9 | { 10 | private static readonly ResourceManager _resourceManager 11 | = new ResourceManager("Microsoft.Extensions.Configuration.Json.Resources", typeof(Resources).GetTypeInfo().Assembly); 12 | 13 | /// 14 | /// File path must be a non-empty string. 15 | /// 16 | internal static string Error_InvalidFilePath 17 | { 18 | get => GetString("Error_InvalidFilePath"); 19 | } 20 | 21 | /// 22 | /// File path must be a non-empty string. 23 | /// 24 | internal static string FormatError_InvalidFilePath() 25 | => GetString("Error_InvalidFilePath"); 26 | 27 | /// 28 | /// Could not parse the JSON file. Error on line number '{0}': '{1}'. 29 | /// 30 | internal static string Error_JSONParseError 31 | { 32 | get => GetString("Error_JSONParseError"); 33 | } 34 | 35 | /// 36 | /// Could not parse the JSON file. Error on line number '{0}': '{1}'. 37 | /// 38 | internal static string FormatError_JSONParseError(object p0, object p1) 39 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_JSONParseError"), p0, p1); 40 | 41 | /// 42 | /// A duplicate key '{0}' was found. 43 | /// 44 | internal static string Error_KeyIsDuplicated 45 | { 46 | get => GetString("Error_KeyIsDuplicated"); 47 | } 48 | 49 | /// 50 | /// A duplicate key '{0}' was found. 51 | /// 52 | internal static string FormatError_KeyIsDuplicated(object p0) 53 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_KeyIsDuplicated"), p0); 54 | 55 | /// 56 | /// Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}. 57 | /// 58 | internal static string Error_UnsupportedJSONToken 59 | { 60 | get => GetString("Error_UnsupportedJSONToken"); 61 | } 62 | 63 | /// 64 | /// Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}. 65 | /// 66 | internal static string FormatError_UnsupportedJSONToken(object p0, object p1, object p2, object p3) 67 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_UnsupportedJSONToken"), p0, p1, p2, p3); 68 | 69 | private static string GetString(string name, params string[] formatterNames) 70 | { 71 | var value = _resourceManager.GetString(name); 72 | 73 | System.Diagnostics.Debug.Assert(value != null); 74 | 75 | if (formatterNames != null) 76 | { 77 | for (var i = 0; i < formatterNames.Length; i++) 78 | { 79 | value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); 80 | } 81 | } 82 | 83 | return value; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Config.KeyPerFile/Config.KeyPerFile.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.KeyPerFile 5 | Microsoft.Extensions.Configuration.KeyPerFile 6 | Configuration provider that uses files in a directory for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Config.KeyPerFile/KeyPerFileConfigurationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.Extensions.Configuration.KeyPerFile; 4 | using Microsoft.Extensions.FileProviders; 5 | 6 | namespace Microsoft.Extensions.Configuration 7 | { 8 | /// 9 | /// Extension methods for registering with . 10 | /// 11 | public static class KeyPerFileConfigurationBuilderExtensions 12 | { 13 | /// 14 | /// Adds configuration using files from a directory. File names are used as the key, 15 | /// file contents are used as the value. 16 | /// 17 | /// The to add to. 18 | /// The path to the directory. 19 | /// Whether the directory is optional. 20 | /// The . 21 | public static IConfigurationBuilder AddKeyPerFile(this IConfigurationBuilder builder, string directoryPath, bool optional) 22 | => builder.AddKeyPerFile(source => 23 | { 24 | // Only try to set the file provider if its not optional or the directory exists 25 | if (!optional || Directory.Exists(directoryPath)) 26 | { 27 | source.FileProvider = new PhysicalFileProvider(directoryPath); 28 | } 29 | source.Optional = optional; 30 | }); 31 | 32 | /// 33 | /// Adds configuration using files from a directory. File names are used as the key, 34 | /// file contents are used as the value. 35 | /// 36 | /// The to add to. 37 | /// Configures the source. 38 | /// The . 39 | public static IConfigurationBuilder AddKeyPerFile(this IConfigurationBuilder builder, Action configureSource) 40 | => builder.Add(configureSource); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Config.KeyPerFile/KeyPerFileConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace Microsoft.Extensions.Configuration.KeyPerFile 6 | { 7 | /// 8 | /// A that uses a directory's files as configuration key/values. 9 | /// 10 | public class KeyPerFileConfigurationProvider : ConfigurationProvider 11 | { 12 | KeyPerFileConfigurationSource Source { get; set; } 13 | 14 | /// 15 | /// Initializes a new instance. 16 | /// 17 | /// The settings. 18 | public KeyPerFileConfigurationProvider(KeyPerFileConfigurationSource source) 19 | => Source = source ?? throw new ArgumentNullException(nameof(source)); 20 | 21 | private static string NormalizeKey(string key) 22 | => key.Replace("__", ConfigurationPath.KeyDelimiter); 23 | 24 | private static string TrimNewLine(string value) 25 | => value.EndsWith(Environment.NewLine) 26 | ? value.Substring(0, value.Length - Environment.NewLine.Length) 27 | : value; 28 | 29 | /// 30 | /// Loads the docker secrets. 31 | /// 32 | public override void Load() 33 | { 34 | Data = new Dictionary(StringComparer.OrdinalIgnoreCase); 35 | 36 | if (Source.FileProvider == null) 37 | { 38 | if (Source.Optional) 39 | { 40 | return; 41 | } 42 | else 43 | { 44 | throw new DirectoryNotFoundException("A non-null file provider for the directory is required when this source is not optional."); 45 | } 46 | } 47 | 48 | var directory = Source.FileProvider.GetDirectoryContents("/"); 49 | if (!directory.Exists && !Source.Optional) 50 | { 51 | throw new DirectoryNotFoundException("The root directory for the FileProvider doesn't exist and is not optional."); 52 | } 53 | 54 | foreach (var file in directory) 55 | { 56 | if (file.IsDirectory) 57 | { 58 | continue; 59 | } 60 | 61 | using (var stream = file.CreateReadStream()) 62 | using (var streamReader = new StreamReader(stream)) 63 | { 64 | if (Source.IgnoreCondition == null || !Source.IgnoreCondition(file.Name)) 65 | { 66 | Data.Add(NormalizeKey(file.Name), TrimNewLine(streamReader.ReadToEnd())); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Config.KeyPerFile/KeyPerFileConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.Extensions.FileProviders; 4 | 5 | namespace Microsoft.Extensions.Configuration.KeyPerFile 6 | { 7 | /// 8 | /// An used to configure . 9 | /// 10 | public class KeyPerFileConfigurationSource : IConfigurationSource 11 | { 12 | /// 13 | /// Constructor; 14 | /// 15 | public KeyPerFileConfigurationSource() 16 | => IgnoreCondition = s => IgnorePrefix != null && s.StartsWith(IgnorePrefix); 17 | 18 | /// 19 | /// The FileProvider whos root "/" directory files will be used as configuration data. 20 | /// 21 | public IFileProvider FileProvider { get; set; } 22 | 23 | /// 24 | /// Files that start with this prefix will be excluded. 25 | /// Defaults to "ignore.". 26 | /// 27 | public string IgnorePrefix { get; set; } = "ignore."; 28 | 29 | /// 30 | /// Used to determine if a file should be ignored using its name. 31 | /// Defaults to using the IgnorePrefix. 32 | /// 33 | public Func IgnoreCondition { get; set; } 34 | 35 | /// 36 | /// If false, will throw if the directory doesn't exist. 37 | /// 38 | public bool Optional { get; set; } 39 | 40 | /// 41 | /// Builds the for this source. 42 | /// 43 | /// The . 44 | /// A 45 | public IConfigurationProvider Build(IConfigurationBuilder builder) 46 | => new KeyPerFileConfigurationProvider(this); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Config.KeyPerFile/README.md: -------------------------------------------------------------------------------- 1 |  2 | This is a configuration provider that uses a directory's files as data. A file's name is the key and the contents are the value. 3 | -------------------------------------------------------------------------------- /src/Config.UserSecrets/Config.UserSecrets.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.UserSecrets 5 | Microsoft.Extensions.Configuration.UserSecrets 6 | Microsoft.Extensions.Configuration.UserSecrets 7 | User secrets configuration provider implementation for Microsoft.Extensions.Configuration. 8 | netstandard2.0 9 | $(PackageTags);secrets;usersecrets 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Config.UserSecrets/PathHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | 7 | namespace Microsoft.Extensions.Configuration.UserSecrets 8 | { 9 | /// 10 | /// Provides paths for user secrets configuration files. 11 | /// 12 | public class PathHelper 13 | { 14 | internal const string SecretsFileName = "secrets.json"; 15 | 16 | /// 17 | /// 18 | /// Returns the path to the JSON file that stores user secrets. 19 | /// 20 | /// 21 | /// This uses the current user profile to locate the secrets file on disk in a location outside of source control. 22 | /// 23 | /// 24 | /// The user secret ID. 25 | /// The full path to the secret file. 26 | public static string GetSecretsPathFromSecretsId(string userSecretsId) 27 | { 28 | if (string.IsNullOrEmpty(userSecretsId)) 29 | { 30 | throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(userSecretsId)); 31 | } 32 | 33 | var badCharIndex = userSecretsId.IndexOfAny(Path.GetInvalidFileNameChars()); 34 | if (badCharIndex != -1) 35 | { 36 | throw new InvalidOperationException( 37 | string.Format( 38 | Resources.Error_Invalid_Character_In_UserSecrets_Id, 39 | userSecretsId[badCharIndex], 40 | badCharIndex)); 41 | } 42 | 43 | const string userSecretsFallbackDir = "DOTNET_USER_SECRETS_FALLBACK_DIR"; 44 | 45 | // For backwards compat, this checks env vars first before using Env.GetFolderPath 46 | var root = Environment.GetEnvironmentVariable("APPDATA") // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\ 47 | ?? Environment.GetEnvironmentVariable("HOME") // On Mac/Linux it goes to ~/.microsoft/usersecrets/ 48 | ?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) 49 | ?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) 50 | ?? Environment.GetEnvironmentVariable(userSecretsFallbackDir); // this fallback is an escape hatch if everything else fails 51 | 52 | if (string.IsNullOrEmpty(root)) 53 | { 54 | throw new InvalidOperationException("Could not determine an appropriate location for storing user secrets. Set the " + userSecretsFallbackDir + " environment variable to a folder where user secrets should be stored."); 55 | } 56 | 57 | if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPDATA"))) 58 | { 59 | return Path.Combine(root, "Microsoft", "UserSecrets", userSecretsId, SecretsFileName); 60 | } 61 | else 62 | { 63 | return Path.Combine(root, ".microsoft", "usersecrets", userSecretsId, SecretsFileName); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Config.UserSecrets/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.UserSecrets.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | -------------------------------------------------------------------------------- /src/Config.UserSecrets/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Extensions.Configuration.UserSecrets 3 | { 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Resources; 7 | 8 | internal static class Resources 9 | { 10 | private static readonly ResourceManager _resourceManager 11 | = new ResourceManager("Microsoft.Extensions.Configuration.UserSecrets.Resources", typeof(Resources).GetTypeInfo().Assembly); 12 | 13 | /// 14 | /// Value cannot be null or an empty string. 15 | /// 16 | internal static string Common_StringNullOrEmpty 17 | { 18 | get => GetString("Common_StringNullOrEmpty"); 19 | } 20 | 21 | /// 22 | /// Value cannot be null or an empty string. 23 | /// 24 | internal static string FormatCommon_StringNullOrEmpty() 25 | => GetString("Common_StringNullOrEmpty"); 26 | 27 | /// 28 | /// Invalid character '{0}' found in the user secrets ID at index '{1}'. 29 | /// 30 | internal static string Error_Invalid_Character_In_UserSecrets_Id 31 | { 32 | get => GetString("Error_Invalid_Character_In_UserSecrets_Id"); 33 | } 34 | 35 | /// 36 | /// Invalid character '{0}' found in the user secrets ID at index '{1}'. 37 | /// 38 | internal static string FormatError_Invalid_Character_In_UserSecrets_Id(object p0, object p1) 39 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_Invalid_Character_In_UserSecrets_Id"), p0, p1); 40 | 41 | /// 42 | /// Could not find 'UserSecretsIdAttribute' on assembly '{0}'. 43 | /// Check that the project for '{0}' has set the 'UserSecretsId' build property. 44 | /// If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package. 45 | /// 46 | internal static string Error_Missing_UserSecretsIdAttribute 47 | { 48 | get => GetString("Error_Missing_UserSecretsIdAttribute"); 49 | } 50 | 51 | /// 52 | /// Could not find 'UserSecretsIdAttribute' on assembly '{0}'. 53 | /// Check that the project for '{0}' has set the 'UserSecretsId' build property. 54 | /// If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package. 55 | /// 56 | internal static string FormatError_Missing_UserSecretsIdAttribute(object p0) 57 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_Missing_UserSecretsIdAttribute"), p0); 58 | 59 | private static string GetString(string name, params string[] formatterNames) 60 | { 61 | var value = _resourceManager.GetString(name); 62 | 63 | System.Diagnostics.Debug.Assert(value != null); 64 | 65 | if (formatterNames != null) 66 | { 67 | for (var i = 0; i < formatterNames.Length; i++) 68 | { 69 | value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); 70 | } 71 | } 72 | 73 | return value; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Config.UserSecrets/UserSecretsIdAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Extensions.Configuration.UserSecrets 7 | { 8 | /// 9 | /// 10 | /// Represents the user secrets ID. 11 | /// 12 | /// 13 | /// In most cases, this attribute is automatically generated during compilation by MSBuild targets 14 | /// included in the UserSecrets NuGet package. These targets use the MSBuild property 'UserSecretsId' 15 | /// to set the value for . 16 | /// 17 | /// 18 | [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] 19 | public class UserSecretsIdAttribute : Attribute 20 | { 21 | /// 22 | /// Initializes an instance of . 23 | /// 24 | /// The user secrets ID. 25 | public UserSecretsIdAttribute(string userSecretId) 26 | { 27 | if (string.IsNullOrEmpty(userSecretId)) 28 | { 29 | throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(userSecretId)); 30 | } 31 | 32 | UserSecretsId = userSecretId; 33 | } 34 | 35 | /// 36 | /// The user secrets ID. 37 | /// 38 | public string UserSecretsId { get; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Config.UserSecrets/build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Config.UserSecrets/build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 7 | 8 | 9 | 10 | <_Parameter1>$(UserSecretsId.Trim()) 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Config.Xml/Config.Xml.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Xml 5 | Microsoft.Extensions.Configuration.Xml 6 | XML configuration provider implementation for Microsoft.Extensions.Configuration. 7 | netstandard2.0 8 | $(PackageTags);xml 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Config.Xml/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.Xml.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | 8 | -------------------------------------------------------------------------------- /src/Config.Xml/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Extensions.Configuration.Xml 3 | { 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Resources; 7 | 8 | internal static class Resources 9 | { 10 | private static readonly ResourceManager _resourceManager 11 | = new ResourceManager("Microsoft.Extensions.Configuration.Xml.Resources", typeof(Resources).GetTypeInfo().Assembly); 12 | 13 | /// 14 | /// File path must be a non-empty string. 15 | /// 16 | internal static string Error_InvalidFilePath 17 | { 18 | get => GetString("Error_InvalidFilePath"); 19 | } 20 | 21 | /// 22 | /// File path must be a non-empty string. 23 | /// 24 | internal static string FormatError_InvalidFilePath() 25 | => GetString("Error_InvalidFilePath"); 26 | 27 | /// 28 | /// A duplicate key '{0}' was found.{1} 29 | /// 30 | internal static string Error_KeyIsDuplicated 31 | { 32 | get => GetString("Error_KeyIsDuplicated"); 33 | } 34 | 35 | /// 36 | /// A duplicate key '{0}' was found.{1} 37 | /// 38 | internal static string FormatError_KeyIsDuplicated(object p0, object p1) 39 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_KeyIsDuplicated"), p0, p1); 40 | 41 | /// 42 | /// XML namespaces are not supported.{0} 43 | /// 44 | internal static string Error_NamespaceIsNotSupported 45 | { 46 | get => GetString("Error_NamespaceIsNotSupported"); 47 | } 48 | 49 | /// 50 | /// XML namespaces are not supported.{0} 51 | /// 52 | internal static string FormatError_NamespaceIsNotSupported(object p0) 53 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_NamespaceIsNotSupported"), p0); 54 | 55 | /// 56 | /// Unsupported node type '{0}' was found.{1} 57 | /// 58 | internal static string Error_UnsupportedNodeType 59 | { 60 | get => GetString("Error_UnsupportedNodeType"); 61 | } 62 | 63 | /// 64 | /// Unsupported node type '{0}' was found.{1} 65 | /// 66 | internal static string FormatError_UnsupportedNodeType(object p0, object p1) 67 | => string.Format(CultureInfo.CurrentCulture, GetString("Error_UnsupportedNodeType"), p0, p1); 68 | 69 | /// 70 | /// Line {0}, position {1}. 71 | /// 72 | internal static string Msg_LineInfo 73 | { 74 | get => GetString("Msg_LineInfo"); 75 | } 76 | 77 | /// 78 | /// Line {0}, position {1}. 79 | /// 80 | internal static string FormatMsg_LineInfo(object p0, object p1) 81 | => string.Format(CultureInfo.CurrentCulture, GetString("Msg_LineInfo"), p0, p1); 82 | 83 | private static string GetString(string name, params string[] formatterNames) 84 | { 85 | var value = _resourceManager.GetString(name); 86 | 87 | System.Diagnostics.Debug.Assert(value != null); 88 | 89 | if (formatterNames != null) 90 | { 91 | for (var i = 0; i < formatterNames.Length; i++) 92 | { 93 | value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); 94 | } 95 | } 96 | 97 | return value; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Config.Xml/XmlConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.Extensions.Configuration.Xml 5 | { 6 | /// 7 | /// An XML file based . 8 | /// 9 | public class XmlConfigurationSource : FileConfigurationSource 10 | { 11 | /// 12 | /// Builds the for this source. 13 | /// 14 | /// The . 15 | /// A 16 | public override IConfigurationProvider Build(IConfigurationBuilder builder) 17 | { 18 | EnsureDefaults(builder); 19 | return new XmlConfigurationProvider(this); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Config.Xml/XmlDocumentDecryptor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using System.Security.Cryptography.Xml; 7 | using System.Xml; 8 | 9 | namespace Microsoft.Extensions.Configuration.Xml 10 | { 11 | /// 12 | /// Class responsible for encrypting and decrypting XML. 13 | /// 14 | public class XmlDocumentDecryptor 15 | { 16 | /// 17 | /// Accesses the singleton decryptor instance. 18 | /// 19 | public static readonly XmlDocumentDecryptor Instance = new XmlDocumentDecryptor(); 20 | 21 | private readonly Func _encryptedXmlFactory; 22 | 23 | /// 24 | /// Initializes a XmlDocumentDecryptor. 25 | /// 26 | // don't create an instance of this directly 27 | protected XmlDocumentDecryptor() 28 | : this(DefaultEncryptedXmlFactory) 29 | { 30 | } 31 | 32 | // for testing only 33 | internal XmlDocumentDecryptor(Func encryptedXmlFactory) 34 | { 35 | _encryptedXmlFactory = encryptedXmlFactory; 36 | } 37 | 38 | private static bool ContainsEncryptedData(XmlDocument document) 39 | { 40 | // EncryptedXml will simply decrypt the document in-place without telling 41 | // us that it did so, so we need to perform a check to see if EncryptedXml 42 | // will actually do anything. The below check for an encrypted data blob 43 | // is the same one that EncryptedXml would have performed. 44 | var namespaceManager = new XmlNamespaceManager(document.NameTable); 45 | namespaceManager.AddNamespace("enc", "http://www.w3.org/2001/04/xmlenc#"); 46 | return (document.SelectSingleNode("//enc:EncryptedData", namespaceManager) != null); 47 | } 48 | 49 | /// 50 | /// Returns an XmlReader that decrypts data transparently. 51 | /// 52 | public XmlReader CreateDecryptingXmlReader(Stream input, XmlReaderSettings settings) 53 | { 54 | // XML-based configurations aren't really all that big, so we can buffer 55 | // the whole thing in memory while we determine decryption operations. 56 | var memStream = new MemoryStream(); 57 | input.CopyTo(memStream); 58 | memStream.Position = 0; 59 | 60 | // First, consume the entire XmlReader as an XmlDocument. 61 | var document = new XmlDocument(); 62 | using (var reader = XmlReader.Create(memStream, settings)) 63 | { 64 | document.Load(reader); 65 | } 66 | memStream.Position = 0; 67 | 68 | if (ContainsEncryptedData(document)) 69 | { 70 | return DecryptDocumentAndCreateXmlReader(document); 71 | } 72 | else 73 | { 74 | // If no decryption would have taken place, return a new fresh reader 75 | // based on the memory stream (which doesn't need to be disposed). 76 | return XmlReader.Create(memStream, settings); 77 | } 78 | } 79 | 80 | /// 81 | /// Creates a reader that can decrypt an encrypted XML document. 82 | /// 83 | /// The document. 84 | /// An XmlReader which can read the document. 85 | protected virtual XmlReader DecryptDocumentAndCreateXmlReader(XmlDocument document) 86 | { 87 | // Perform the actual decryption step, updating the XmlDocument in-place. 88 | var encryptedXml = _encryptedXmlFactory(document); 89 | encryptedXml.DecryptDocument(); 90 | 91 | // Finally, return the new XmlReader from the updated XmlDocument. 92 | // Error messages based on this XmlReader won't show line numbers, 93 | // but that's fine since we transformed the document anyway. 94 | return document.CreateNavigator().ReadSubtree(); 95 | } 96 | 97 | private static EncryptedXml DefaultEncryptedXmlFactory(XmlDocument document) 98 | => new EncryptedXml(document); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Config/ChainedBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// IConfigurationBuilder extension methods for the chaind configuration provider. 11 | /// 12 | public static class ChainedBuilderExtensions 13 | { 14 | /// 15 | /// Adds an existing configuration to . 16 | /// 17 | /// The to add to. 18 | /// The to add. 19 | /// The . 20 | public static IConfigurationBuilder AddConfiguration(this IConfigurationBuilder configurationBuilder, IConfiguration config) 21 | { 22 | if (configurationBuilder == null) 23 | { 24 | throw new ArgumentNullException(nameof(configurationBuilder)); 25 | } 26 | if (config == null) 27 | { 28 | throw new ArgumentNullException(nameof(config)); 29 | } 30 | 31 | configurationBuilder.Add(new ChainedConfigurationSource { Configuration = config }); 32 | return configurationBuilder; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Config/ChainedConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using Microsoft.Extensions.Primitives; 8 | 9 | namespace Microsoft.Extensions.Configuration 10 | { 11 | /// 12 | /// Chained implementation of 13 | /// 14 | public class ChainedConfigurationProvider : IConfigurationProvider 15 | { 16 | private readonly IConfiguration _config; 17 | 18 | /// 19 | /// Initialize a new instance from the source configuration. 20 | /// 21 | /// The source configuration. 22 | public ChainedConfigurationProvider(ChainedConfigurationSource source) 23 | { 24 | if (source == null) 25 | { 26 | throw new ArgumentNullException(nameof(source)); 27 | } 28 | if (source.Configuration == null) 29 | { 30 | throw new ArgumentNullException(nameof(source.Configuration)); 31 | } 32 | 33 | _config = source.Configuration; 34 | } 35 | 36 | /// 37 | /// Tries to get a configuration value for the specified key. 38 | /// 39 | /// The key. 40 | /// The value. 41 | /// True if a value for the specified key was found, otherwise false. 42 | public bool TryGet(string key, out string value) 43 | { 44 | value = _config[key]; 45 | return !string.IsNullOrEmpty(value); 46 | } 47 | 48 | /// 49 | /// Sets a configuration value for the specified key. 50 | /// 51 | /// The key. 52 | /// The value. 53 | public void Set(string key, string value) => _config[key] = value; 54 | 55 | /// 56 | /// Returns a change token if this provider supports change tracking, null otherwise. 57 | /// 58 | /// 59 | public IChangeToken GetReloadToken() => _config.GetReloadToken(); 60 | 61 | /// 62 | /// Loads configuration values from the source represented by this . 63 | /// 64 | public void Load() { } 65 | 66 | /// 67 | /// Returns the immediate descendant configuration keys for a given parent path based on this 68 | /// 's data and the set of keys returned by all the preceding 69 | /// s. 70 | /// 71 | /// The child keys returned by the preceding providers for the same parent path. 72 | /// The parent path. 73 | /// The child keys. 74 | public IEnumerable GetChildKeys( 75 | IEnumerable earlierKeys, 76 | string parentPath) 77 | { 78 | var section = parentPath == null ? _config : _config.GetSection(parentPath); 79 | var children = section.GetChildren(); 80 | var keys = new List(); 81 | keys.AddRange(children.Select(c => c.Key)); 82 | return keys.Concat(earlierKeys) 83 | .OrderBy(k => k, ConfigurationKeyComparer.Instance); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Config/ChainedConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.Extensions.Configuration 5 | { 6 | /// 7 | /// Represents a chained IConfiguration as an . 8 | /// 9 | public class ChainedConfigurationSource : IConfigurationSource 10 | { 11 | /// 12 | /// The chained configuration. 13 | /// 14 | public IConfiguration Configuration { get; set; } 15 | 16 | /// 17 | /// Builds the for this source. 18 | /// 19 | /// The . 20 | /// A 21 | public IConfigurationProvider Build(IConfigurationBuilder builder) 22 | => new ChainedConfigurationProvider(this); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Config/Config.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration 5 | Microsoft.Extensions.Configuration 6 | Implementation of key-value pair based configuration for Microsoft.Extensions.Configuration. Includes the memory configuration provider. 7 | netstandard2.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Config/ConfigurationBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// Used to build key/value based configuration settings for use in an application. 11 | /// 12 | public class ConfigurationBuilder : IConfigurationBuilder 13 | { 14 | /// 15 | /// Returns the sources used to obtain configuration values. 16 | /// 17 | public IList Sources { get; } = new List(); 18 | 19 | /// 20 | /// Gets a key/value collection that can be used to share data between the 21 | /// and the registered s. 22 | /// 23 | public IDictionary Properties { get; } = new Dictionary(); 24 | 25 | /// 26 | /// Adds a new configuration source. 27 | /// 28 | /// The configuration source to add. 29 | /// The same . 30 | public IConfigurationBuilder Add(IConfigurationSource source) 31 | { 32 | if (source == null) 33 | { 34 | throw new ArgumentNullException(nameof(source)); 35 | } 36 | 37 | Sources.Add(source); 38 | return this; 39 | } 40 | 41 | /// 42 | /// Builds an with keys and values from the set of providers registered in 43 | /// . 44 | /// 45 | /// An with keys and values from the registered providers. 46 | public IConfigurationRoot Build() 47 | { 48 | var providers = new List(); 49 | foreach (var source in Sources) 50 | { 51 | var provider = source.Build(this); 52 | providers.Add(provider); 53 | } 54 | return new ConfigurationRoot(providers); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Config/ConfigurationKeyComparer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.Extensions.Configuration 8 | { 9 | /// 10 | /// IComparer implementation used to order configuration keys. 11 | /// 12 | public class ConfigurationKeyComparer : IComparer 13 | { 14 | private static readonly string[] _keyDelimiterArray = new[] { ConfigurationPath.KeyDelimiter }; 15 | 16 | /// 17 | /// The default instance. 18 | /// 19 | public static ConfigurationKeyComparer Instance { get; } = new ConfigurationKeyComparer(); 20 | 21 | /// 22 | /// Compares two strings. 23 | /// 24 | /// First string. 25 | /// Second string. 26 | /// 27 | public int Compare(string x, string y) 28 | { 29 | var xParts = x?.Split(_keyDelimiterArray, StringSplitOptions.RemoveEmptyEntries) ?? new string[0]; 30 | var yParts = y?.Split(_keyDelimiterArray, StringSplitOptions.RemoveEmptyEntries) ?? new string[0]; 31 | 32 | // Compare each part until we get two parts that are not equal 33 | for (int i = 0; i < Math.Min(xParts.Length, yParts.Length); i++) 34 | { 35 | x = xParts[i]; 36 | y = yParts[i]; 37 | 38 | var value1 = 0; 39 | var value2 = 0; 40 | 41 | var xIsInt = x != null && int.TryParse(x, out value1); 42 | var yIsInt = y != null && int.TryParse(y, out value2); 43 | 44 | int result = 0; 45 | 46 | if (!xIsInt && !yIsInt) 47 | { 48 | // Both are strings 49 | result = string.Compare(x, y, StringComparison.OrdinalIgnoreCase); 50 | } 51 | else if (xIsInt && yIsInt) 52 | { 53 | // Both are int 54 | result = value1 - value2; 55 | } 56 | else 57 | { 58 | // Only one of them is int 59 | result = xIsInt ? -1 : 1; 60 | } 61 | 62 | if (result != 0) 63 | { 64 | // One of them is different 65 | return result; 66 | } 67 | } 68 | 69 | // If we get here, the common parts are equal. 70 | // If they are of the same length, then they are totally identical 71 | return xParts.Length - yParts.Length; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Config/ConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading; 8 | using Microsoft.Extensions.Primitives; 9 | 10 | namespace Microsoft.Extensions.Configuration 11 | { 12 | /// 13 | /// Base helper class for implementing an 14 | /// 15 | public abstract class ConfigurationProvider : IConfigurationProvider 16 | { 17 | private ConfigurationReloadToken _reloadToken = new ConfigurationReloadToken(); 18 | 19 | /// 20 | /// Initializes a new 21 | /// 22 | protected ConfigurationProvider() 23 | { 24 | Data = new Dictionary(StringComparer.OrdinalIgnoreCase); 25 | } 26 | 27 | /// 28 | /// The configuration key value pairs for this provider. 29 | /// 30 | protected IDictionary Data { get; set; } 31 | 32 | /// 33 | /// Attempts to find a value with the given key, returns true if one is found, false otherwise. 34 | /// 35 | /// The key to lookup. 36 | /// The value found at key if one is found. 37 | /// True if key has a value, false otherwise. 38 | public virtual bool TryGet(string key, out string value) 39 | => Data.TryGetValue(key, out value); 40 | 41 | /// 42 | /// Sets a value for a given key. 43 | /// 44 | /// The configuration key to set. 45 | /// The value to set. 46 | public virtual void Set(string key, string value) 47 | => Data[key] = value; 48 | 49 | /// 50 | /// Loads (or reloads) the data for this provider. 51 | /// 52 | public virtual void Load() 53 | { } 54 | 55 | /// 56 | /// Returns the list of keys that this provider has. 57 | /// 58 | /// The earlier keys that other providers contain. 59 | /// The path for the parent IConfiguration. 60 | /// The list of keys for this provider. 61 | public virtual IEnumerable GetChildKeys( 62 | IEnumerable earlierKeys, 63 | string parentPath) 64 | { 65 | var prefix = parentPath == null ? string.Empty : parentPath + ConfigurationPath.KeyDelimiter; 66 | 67 | return Data 68 | .Where(kv => kv.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) 69 | .Select(kv => Segment(kv.Key, prefix.Length)) 70 | .Concat(earlierKeys) 71 | .OrderBy(k => k, ConfigurationKeyComparer.Instance); 72 | } 73 | 74 | private static string Segment(string key, int prefixLength) 75 | { 76 | var indexOf = key.IndexOf(ConfigurationPath.KeyDelimiter, prefixLength, StringComparison.OrdinalIgnoreCase); 77 | return indexOf < 0 ? key.Substring(prefixLength) : key.Substring(prefixLength, indexOf - prefixLength); 78 | } 79 | 80 | /// 81 | /// Returns a that can be used to listen when this provider is reloaded. 82 | /// 83 | /// 84 | public IChangeToken GetReloadToken() 85 | { 86 | return _reloadToken; 87 | } 88 | 89 | /// 90 | /// Triggers the reload change token and creates a new one. 91 | /// 92 | protected void OnReload() 93 | { 94 | var previousToken = Interlocked.Exchange(ref _reloadToken, new ConfigurationReloadToken()); 95 | previousToken.OnReload(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Config/ConfigurationReloadToken.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Threading; 6 | using Microsoft.Extensions.Primitives; 7 | 8 | namespace Microsoft.Extensions.Configuration 9 | { 10 | /// 11 | /// Implements 12 | /// 13 | public class ConfigurationReloadToken : IChangeToken 14 | { 15 | private CancellationTokenSource _cts = new CancellationTokenSource(); 16 | 17 | /// 18 | /// Indicates if this token will proactively raise callbacks. Callbacks are still guaranteed to be invoked, eventually. 19 | /// 20 | public bool ActiveChangeCallbacks => true; 21 | 22 | /// 23 | /// Gets a value that indicates if a change has occurred. 24 | /// 25 | public bool HasChanged => _cts.IsCancellationRequested; 26 | 27 | /// 28 | /// Registers for a callback that will be invoked when the entry has changed. 29 | /// MUST be set before the callback is invoked. 30 | /// 31 | /// The callback to invoke. 32 | /// State to be passed into the callback. 33 | /// 34 | public IDisposable RegisterChangeCallback(Action callback, object state) => _cts.Token.Register(callback, state); 35 | 36 | /// 37 | /// Used to trigger the change token when a reload occurs. 38 | /// 39 | public void OnReload() => _cts.Cancel(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Config/ConfigurationRoot.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading; 8 | using Microsoft.Extensions.Primitives; 9 | 10 | namespace Microsoft.Extensions.Configuration 11 | { 12 | /// 13 | /// The root node for a configuration. 14 | /// 15 | public class ConfigurationRoot : IConfigurationRoot 16 | { 17 | private IList _providers; 18 | private ConfigurationReloadToken _changeToken = new ConfigurationReloadToken(); 19 | 20 | /// 21 | /// Initializes a Configuration root with a list of providers. 22 | /// 23 | /// The s for this configuration. 24 | public ConfigurationRoot(IList providers) 25 | { 26 | if (providers == null) 27 | { 28 | throw new ArgumentNullException(nameof(providers)); 29 | } 30 | 31 | _providers = providers; 32 | foreach (var p in providers) 33 | { 34 | p.Load(); 35 | ChangeToken.OnChange(() => p.GetReloadToken(), () => RaiseChanged()); 36 | } 37 | } 38 | 39 | /// 40 | /// The s for this configuration. 41 | /// 42 | public IEnumerable Providers => _providers; 43 | 44 | /// 45 | /// Gets or sets the value corresponding to a configuration key. 46 | /// 47 | /// The configuration key. 48 | /// The configuration value. 49 | public string this[string key] 50 | { 51 | get 52 | { 53 | foreach (var provider in _providers.Reverse()) 54 | { 55 | string value; 56 | 57 | if (provider.TryGet(key, out value)) 58 | { 59 | return value; 60 | } 61 | } 62 | 63 | return null; 64 | } 65 | 66 | set 67 | { 68 | if (!_providers.Any()) 69 | { 70 | throw new InvalidOperationException(Resources.Error_NoSources); 71 | } 72 | 73 | foreach (var provider in _providers) 74 | { 75 | provider.Set(key, value); 76 | } 77 | } 78 | } 79 | 80 | /// 81 | /// Gets the immediate children sub-sections. 82 | /// 83 | /// 84 | public IEnumerable GetChildren() => GetChildrenImplementation(null); 85 | 86 | internal IEnumerable GetChildrenImplementation(string path) 87 | { 88 | return _providers 89 | .Aggregate(Enumerable.Empty(), 90 | (seed, source) => source.GetChildKeys(seed, path)) 91 | .Distinct() 92 | .Select(key => GetSection(path == null ? key : ConfigurationPath.Combine(path, key))); 93 | } 94 | 95 | /// 96 | /// Returns a that can be used to observe when this configuration is reloaded. 97 | /// 98 | /// 99 | public IChangeToken GetReloadToken() => _changeToken; 100 | 101 | /// 102 | /// Gets a configuration sub-section with the specified key. 103 | /// 104 | /// The key of the configuration section. 105 | /// The . 106 | /// 107 | /// This method will never return null. If no matching sub-section is found with the specified key, 108 | /// an empty will be returned. 109 | /// 110 | public IConfigurationSection GetSection(string key) 111 | => new ConfigurationSection(this, key); 112 | 113 | /// 114 | /// Force the configuration values to be reloaded from the underlying sources. 115 | /// 116 | public void Reload() 117 | { 118 | foreach (var provider in _providers) 119 | { 120 | provider.Load(); 121 | } 122 | RaiseChanged(); 123 | } 124 | 125 | private void RaiseChanged() 126 | { 127 | var previousToken = Interlocked.Exchange(ref _changeToken, new ConfigurationReloadToken()); 128 | previousToken.OnReload(); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/Config/ConfigurationSection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.Extensions.Primitives; 7 | 8 | namespace Microsoft.Extensions.Configuration 9 | { 10 | /// 11 | /// Represents a section of application configuration values. 12 | /// 13 | public class ConfigurationSection : IConfigurationSection 14 | { 15 | private readonly ConfigurationRoot _root; 16 | private readonly string _path; 17 | private string _key; 18 | 19 | /// 20 | /// Initializes a new instance. 21 | /// 22 | /// The configuration root. 23 | /// The path to this section. 24 | public ConfigurationSection(ConfigurationRoot root, string path) 25 | { 26 | if (root == null) 27 | { 28 | throw new ArgumentNullException(nameof(root)); 29 | } 30 | 31 | if (path == null) 32 | { 33 | throw new ArgumentNullException(nameof(path)); 34 | } 35 | 36 | _root = root; 37 | _path = path; 38 | } 39 | 40 | /// 41 | /// Gets the full path to this section from the . 42 | /// 43 | public string Path => _path; 44 | 45 | /// 46 | /// Gets the key this section occupies in its parent. 47 | /// 48 | public string Key 49 | { 50 | get 51 | { 52 | if (_key == null) 53 | { 54 | // Key is calculated lazily as last portion of Path 55 | _key = ConfigurationPath.GetSectionKey(_path); 56 | } 57 | return _key; 58 | } 59 | } 60 | 61 | /// 62 | /// Gets or sets the section value. 63 | /// 64 | public string Value 65 | { 66 | get 67 | { 68 | return _root[Path]; 69 | } 70 | set 71 | { 72 | _root[Path] = value; 73 | } 74 | } 75 | 76 | /// 77 | /// Gets or sets the value corresponding to a configuration key. 78 | /// 79 | /// The configuration key. 80 | /// The configuration value. 81 | public string this[string key] 82 | { 83 | get 84 | { 85 | return _root[ConfigurationPath.Combine(Path, key)]; 86 | } 87 | 88 | set 89 | { 90 | _root[ConfigurationPath.Combine(Path, key)] = value; 91 | } 92 | } 93 | 94 | /// 95 | /// Gets a configuration sub-section with the specified key. 96 | /// 97 | /// The key of the configuration section. 98 | /// The . 99 | /// 100 | /// This method will never return null. If no matching sub-section is found with the specified key, 101 | /// an empty will be returned. 102 | /// 103 | public IConfigurationSection GetSection(string key) => _root.GetSection(ConfigurationPath.Combine(Path, key)); 104 | 105 | /// 106 | /// Gets the immediate descendant configuration sub-sections. 107 | /// 108 | /// The configuration sub-sections. 109 | public IEnumerable GetChildren() => _root.GetChildrenImplementation(Path); 110 | 111 | /// 112 | /// Returns a that can be used to observe when this configuration is reloaded. 113 | /// 114 | /// 115 | public IChangeToken GetReloadToken() => _root.GetReloadToken(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Config/MemoryConfigurationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.Extensions.Configuration.Memory; 7 | 8 | namespace Microsoft.Extensions.Configuration 9 | { 10 | /// 11 | /// IConfigurationBuilder extension methods for the MemoryConfigurationProvider. 12 | /// 13 | public static class MemoryConfigurationBuilderExtensions 14 | { 15 | /// 16 | /// Adds the memory configuration provider to . 17 | /// 18 | /// The to add to. 19 | /// The . 20 | public static IConfigurationBuilder AddInMemoryCollection(this IConfigurationBuilder configurationBuilder) 21 | { 22 | if (configurationBuilder == null) 23 | { 24 | throw new ArgumentNullException(nameof(configurationBuilder)); 25 | } 26 | 27 | configurationBuilder.Add(new MemoryConfigurationSource()); 28 | return configurationBuilder; 29 | } 30 | 31 | /// 32 | /// Adds the memory configuration provider to . 33 | /// 34 | /// The to add to. 35 | /// The data to add to memory configuration provider. 36 | /// The . 37 | public static IConfigurationBuilder AddInMemoryCollection( 38 | this IConfigurationBuilder configurationBuilder, 39 | IEnumerable> initialData) 40 | { 41 | if (configurationBuilder == null) 42 | { 43 | throw new ArgumentNullException(nameof(configurationBuilder)); 44 | } 45 | 46 | configurationBuilder.Add(new MemoryConfigurationSource { InitialData = initialData }); 47 | return configurationBuilder; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/Config/MemoryConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace Microsoft.Extensions.Configuration.Memory 9 | { 10 | /// 11 | /// In-memory implementation of 12 | /// 13 | public class MemoryConfigurationProvider : ConfigurationProvider, IEnumerable> 14 | { 15 | private readonly MemoryConfigurationSource _source; 16 | 17 | /// 18 | /// Initialize a new instance from the source. 19 | /// 20 | /// The source settings. 21 | public MemoryConfigurationProvider(MemoryConfigurationSource source) 22 | { 23 | if (source == null) 24 | { 25 | throw new ArgumentNullException(nameof(source)); 26 | } 27 | 28 | _source = source; 29 | 30 | if (_source.InitialData != null) 31 | { 32 | foreach (var pair in _source.InitialData) 33 | { 34 | Data.Add(pair.Key, pair.Value); 35 | } 36 | } 37 | } 38 | 39 | /// 40 | /// Add a new key and value pair. 41 | /// 42 | /// The configuration key. 43 | /// The configuration value. 44 | public void Add(string key, string value) 45 | { 46 | Data.Add(key, value); 47 | } 48 | 49 | /// 50 | /// Returns an enumerator that iterates through the collection. 51 | /// 52 | /// An enumerator that can be used to iterate through the collection. 53 | public IEnumerator> GetEnumerator() 54 | { 55 | return Data.GetEnumerator(); 56 | } 57 | 58 | /// 59 | /// Returns an enumerator that iterates through the collection. 60 | /// 61 | /// An enumerator that can be used to iterate through the collection. 62 | IEnumerator IEnumerable.GetEnumerator() 63 | { 64 | return GetEnumerator(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Config/MemoryConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.Extensions.Configuration.Memory 7 | { 8 | /// 9 | /// Represents in-memory data as an . 10 | /// 11 | public class MemoryConfigurationSource : IConfigurationSource 12 | { 13 | /// 14 | /// The initial key value configuration pairs. 15 | /// 16 | public IEnumerable> InitialData { get; set; } 17 | 18 | /// 19 | /// Builds the for this source. 20 | /// 21 | /// The . 22 | /// A 23 | public IConfigurationProvider Build(IConfigurationBuilder builder) 24 | { 25 | return new MemoryConfigurationProvider(this); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Config/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | 8 | -------------------------------------------------------------------------------- /src/Config/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Extensions.Configuration 3 | { 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Resources; 7 | 8 | internal static class Resources 9 | { 10 | private static readonly ResourceManager _resourceManager 11 | = new ResourceManager("Microsoft.Extensions.Configuration.Resources", typeof(Resources).GetTypeInfo().Assembly); 12 | 13 | /// 14 | /// A configuration source is not registered. Please register one before setting a value. 15 | /// 16 | internal static string Error_NoSources 17 | { 18 | get => GetString("Error_NoSources"); 19 | } 20 | 21 | /// 22 | /// A configuration source is not registered. Please register one before setting a value. 23 | /// 24 | internal static string FormatError_NoSources() 25 | => GetString("Error_NoSources"); 26 | 27 | private static string GetString(string name, params string[] formatterNames) 28 | { 29 | var value = _resourceManager.GetString(name); 30 | 31 | System.Diagnostics.Debug.Assert(value != null); 32 | 33 | if (formatterNames != null) 34 | { 35 | for (var i = 0; i < formatterNames.Length; i++) 36 | { 37 | value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); 38 | } 39 | } 40 | 41 | return value; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | configuration 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/Config.AzureKeyVault.Test/Config.AzureKeyVault.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.AzureKeyVault.Test 5 | Microsoft.Extensions.Configuration.AzureKeyVault.Test 6 | net461 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/Config.Binder.Test/Config.Binder.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Microsoft.Extensions.Configuration.Binder.Test 5 | Microsoft.Extensions.Configuration.Binder.Test 6 | netcoreapp2.2;net461 7 | netcoreapp2.2 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/Config.CommandLine.Test/Config.CommandLine.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.CommandLine.Test 5 | Microsoft.Extensions.Configuration.CommandLine.Test 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/Config.EnvironmentVariables.Test/Config.EnvironmentVariables.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.EnvironmentVariables.Test 5 | Microsoft.Extensions.Configuration.EnvironmentVariables.Test 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/Config.FileExtensions.Test/Config.FileExtensions.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.FileExtensions.Test 5 | Microsoft.Extensions.Configuration.FileExtensions.Test 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/Config.FileExtensions.Test/FileConfigurationBuilderExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using Microsoft.Extensions.FileProviders; 7 | using Xunit; 8 | 9 | namespace Microsoft.Extensions.Configuration.Json 10 | { 11 | public class FileConfigurationBuilderExtensionsTest 12 | { 13 | [Fact] 14 | public void SetFileProvider_ThrowsIfBasePathIsNull() 15 | { 16 | // Arrange 17 | var configurationBuilder = new ConfigurationBuilder(); 18 | 19 | // Act and Assert 20 | var ex = Assert.Throws(() => configurationBuilder.SetBasePath(basePath: null)); 21 | Assert.Equal("basePath", ex.ParamName); 22 | } 23 | 24 | [Fact] 25 | public void SetFileProvider_CheckPropertiesValueOnBuilder() 26 | { 27 | var expectedBasePath = Directory.GetCurrentDirectory(); 28 | var configurationBuilder = new ConfigurationBuilder(); 29 | 30 | configurationBuilder.SetBasePath(expectedBasePath); 31 | var physicalProvider = configurationBuilder.GetFileProvider() as PhysicalFileProvider; 32 | Assert.NotNull(physicalProvider); 33 | Assert.Equal(EnsureTrailingSlash(expectedBasePath), physicalProvider.Root); 34 | } 35 | 36 | [Fact] 37 | public void GetFileProvider_ReturnPhysicalProviderWithBaseDirectoryIfNotSet() 38 | { 39 | // Arrange 40 | var configurationBuilder = new ConfigurationBuilder(); 41 | 42 | // Act 43 | var physicalProvider = configurationBuilder.GetFileProvider() as PhysicalFileProvider; 44 | 45 | string expectedPath; 46 | 47 | expectedPath = AppContext.BaseDirectory; 48 | 49 | Assert.NotNull(physicalProvider); 50 | Assert.Equal(EnsureTrailingSlash(expectedPath), physicalProvider.Root); 51 | } 52 | 53 | private static string EnsureTrailingSlash(string path) 54 | { 55 | if (!string.IsNullOrEmpty(path) && 56 | path[path.Length - 1] != Path.DirectorySeparatorChar) 57 | { 58 | return path + Path.DirectorySeparatorChar; 59 | } 60 | 61 | return path; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /test/Config.FunctionalTests/Config.FunctionalTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.FunctionalTests 5 | Microsoft.Extensions.Configuration.FunctionalTests 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/Config.FunctionalTests/DisposableFileSystem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | 7 | namespace Microsoft.Extensions.Configuration.Test 8 | { 9 | public class DisposableFileSystem : IDisposable 10 | { 11 | public DisposableFileSystem() 12 | { 13 | RootPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 14 | Directory.CreateDirectory(RootPath); 15 | DirectoryInfo = new DirectoryInfo(RootPath); 16 | } 17 | 18 | public string RootPath { get; } 19 | 20 | public DirectoryInfo DirectoryInfo { get; } 21 | 22 | public DisposableFileSystem CreateFolder(string path) 23 | { 24 | Directory.CreateDirectory(Path.Combine(RootPath, path)); 25 | return this; 26 | } 27 | 28 | public DisposableFileSystem WriteFile(string path, string text = "temp") 29 | { 30 | File.WriteAllText(Path.Combine(RootPath, path), text); 31 | return this; 32 | } 33 | 34 | public DisposableFileSystem DeleteFile(string path) 35 | { 36 | File.Delete(Path.Combine(RootPath, path)); 37 | return this; 38 | } 39 | 40 | public DisposableFileSystem CreateFiles(params string[] fileRelativePaths) 41 | { 42 | foreach (var path in fileRelativePaths) 43 | { 44 | var fullPath = Path.Combine(RootPath, path); 45 | Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); 46 | 47 | File.WriteAllText( 48 | fullPath, 49 | string.Format("Automatically generated for testing on {0:yyyy}/{0:MM}/{0:dd} {0:hh}:{0:mm}:{0:ss}", DateTime.UtcNow)); 50 | } 51 | 52 | return this; 53 | } 54 | 55 | public void Dispose() 56 | { 57 | try 58 | { 59 | Directory.Delete(RootPath, true); 60 | } 61 | catch 62 | { 63 | // Don't throw if this fails. 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /test/Config.FunctionalTests/test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | XmlValue3 6 | XmlValue4 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/Config.Ini.Test/Config.Ini.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Ini.Test 5 | Microsoft.Extensions.Configuration.Ini.Test 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/Config.Ini.Test/IniConfigurationExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using Xunit; 7 | 8 | namespace Microsoft.Extensions.Configuration.Ini.Test 9 | { 10 | public class IniConfigurationExtensionsTest 11 | { 12 | [Theory] 13 | [InlineData(null)] 14 | [InlineData("")] 15 | public void AddIniFile_ThrowsIfFilePathIsNullOrEmpty(string path) 16 | { 17 | // Arrange 18 | var configurationBuilder = new ConfigurationBuilder(); 19 | 20 | // Act and Assert 21 | var ex = Assert.Throws( 22 | () => IniConfigurationExtensions.AddIniFile(configurationBuilder, path)); 23 | Assert.Equal("path", ex.ParamName); 24 | Assert.StartsWith("File path must be a non-empty string.", ex.Message); 25 | } 26 | 27 | [Fact] 28 | public void AddIniFile_ThrowsIfFileDoesNotExistAtPath() 29 | { 30 | // Arrange 31 | var path = "file-does-not-exist.ini"; 32 | 33 | // Act and Assert 34 | var ex = Assert.Throws(() => new ConfigurationBuilder().AddIniFile(path).Build()); 35 | Assert.StartsWith($"The configuration file '{path}' was not found and is not optional. The physical path is '", ex.Message); 36 | } 37 | 38 | [Fact] 39 | public void AddIniFile_DoesNotThrowsIfFileDoesNotExistAtPathAndOptional() 40 | { 41 | // Arrange 42 | var path = "file-does-not-exist.ini"; 43 | 44 | // Act and Assert 45 | new ConfigurationBuilder().AddIniFile(path, optional: true).Build(); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/Config.Json.Test/Config.Json.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Json.Test 5 | Microsoft.Extensions.Configuration.Json.Test 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/Config.Json.Test/JsonConfigurationExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using Xunit; 7 | 8 | namespace Microsoft.Extensions.Configuration.Json 9 | { 10 | public class JsonConfigurationExtensionsTest 11 | { 12 | [Theory] 13 | [InlineData(null)] 14 | [InlineData("")] 15 | public void AddJsonFile_ThrowsIfFilePathIsNullOrEmpty(string path) 16 | { 17 | // Arrange 18 | var configurationBuilder = new ConfigurationBuilder(); 19 | 20 | // Act and Assert 21 | var ex = Assert.Throws(() => JsonConfigurationExtensions.AddJsonFile(configurationBuilder, path)); 22 | Assert.Equal("path", ex.ParamName); 23 | Assert.StartsWith("File path must be a non-empty string.", ex.Message); 24 | } 25 | 26 | [Fact] 27 | public void AddJsonFile_ThrowsIfFileDoesNotExistAtPath() 28 | { 29 | // Arrange 30 | var path = "file-does-not-exist.json"; 31 | 32 | // Act and Assert 33 | var ex = Assert.Throws(() => new ConfigurationBuilder().AddJsonFile(path).Build()); 34 | Assert.StartsWith($"The configuration file '{path}' was not found and is not optional. The physical path is '", ex.Message); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/Config.KeyPerFile.Test/Config.KeyPerFile.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.KeyPerFile.Test 5 | Microsoft.Extensions.Configuration.KeyPerFile.Test 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/Config.Test.Common/Config.Test.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Test.Common 5 | Microsoft.Extensions.Configuration.Test.Common 6 | netstandard2.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/Config.Test.Common/ConfigurationProviderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Extensions.Configuration.Test 7 | { 8 | public static class ConfigurationProviderExtensions 9 | { 10 | public static string Get(this IConfigurationProvider provider, string key) 11 | { 12 | string value; 13 | 14 | if (!provider.TryGet(key, out value)) 15 | { 16 | throw new InvalidOperationException("Key not found"); 17 | } 18 | 19 | return value; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /test/Config.Test.Common/TestStreamHelpers.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using Microsoft.Extensions.FileProviders; 7 | using Microsoft.Extensions.Primitives; 8 | 9 | namespace Microsoft.Extensions.Configuration.Test 10 | { 11 | public static class TestStreamHelpers 12 | { 13 | public static readonly string ArbitraryFilePath = "Unit tests do not touch file system"; 14 | 15 | public static IFileProvider StringToFileProvider(string str) 16 | { 17 | return new TestFileProvider(str); 18 | 19 | } 20 | 21 | private class TestFile : IFileInfo 22 | { 23 | private readonly string _data; 24 | 25 | public TestFile(string str) 26 | { 27 | _data = str; 28 | } 29 | 30 | public bool Exists 31 | { 32 | get 33 | { 34 | return true; 35 | } 36 | } 37 | 38 | public bool IsDirectory 39 | { 40 | get 41 | { 42 | return false; 43 | } 44 | } 45 | 46 | public DateTimeOffset LastModified 47 | { 48 | get 49 | { 50 | throw new NotImplementedException(); 51 | } 52 | } 53 | 54 | public long Length 55 | { 56 | get 57 | { 58 | throw new NotImplementedException(); 59 | } 60 | } 61 | 62 | public string Name 63 | { 64 | get 65 | { 66 | throw new NotImplementedException(); 67 | } 68 | } 69 | 70 | public string PhysicalPath 71 | { 72 | get 73 | { 74 | throw new NotImplementedException(); 75 | } 76 | } 77 | 78 | public Stream CreateReadStream() 79 | { 80 | return StringToStream(_data); 81 | } 82 | } 83 | 84 | private class TestFileProvider : IFileProvider 85 | { 86 | private string _data; 87 | public TestFileProvider(string str) 88 | { 89 | _data = str; 90 | } 91 | 92 | public IDirectoryContents GetDirectoryContents(string subpath) 93 | { 94 | throw new NotImplementedException(); 95 | } 96 | 97 | public IFileInfo GetFileInfo(string subpath) 98 | { 99 | return new TestFile(_data); 100 | } 101 | 102 | public IChangeToken Watch(string filter) 103 | { 104 | throw new NotImplementedException(); 105 | } 106 | } 107 | 108 | public static Stream StringToStream(string str) 109 | { 110 | var memStream = new MemoryStream(); 111 | var textWriter = new StreamWriter(memStream); 112 | textWriter.Write(str); 113 | textWriter.Flush(); 114 | memStream.Seek(0, SeekOrigin.Begin); 115 | 116 | return memStream; 117 | } 118 | 119 | public static string StreamToString(Stream stream) 120 | { 121 | stream.Seek(0, SeekOrigin.Begin); 122 | var reader = new StreamReader(stream); 123 | 124 | return reader.ReadToEnd(); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /test/Config.Test/Config.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Test 5 | Microsoft.Extensions.Configuration.Test 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/Config.Test/ConfigurationPathComparerTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Xunit; 6 | 7 | namespace Microsoft.Extensions.Configuration.Test 8 | { 9 | public class ConfigurationPathComparerTest 10 | { 11 | [Fact] 12 | public void CompareWithNull() 13 | { 14 | ComparerTest(null, null, 0); 15 | ComparerTest(null, "a", -1); 16 | ComparerTest("b", null, 1); 17 | } 18 | 19 | [Fact] 20 | public void CompareWithSameLength() 21 | { 22 | ComparerTest("a", "a", 0); 23 | ComparerTest("a", "A", 0); 24 | 25 | ComparerTest("aB", "Ab", 0); 26 | } 27 | 28 | [Fact] 29 | public void CompareWithDifferentLengths() 30 | { 31 | ComparerTest("a", "aa", -1); 32 | ComparerTest("aa", "a", 1); 33 | } 34 | 35 | [Fact] 36 | public void CompareWithLetters() 37 | { 38 | ComparerTest("a", "b", -1); 39 | ComparerTest("b", "a", 1); 40 | } 41 | 42 | [Fact] 43 | public void CompareWithNumbers() 44 | { 45 | ComparerTest("000", "0", 0); 46 | ComparerTest("001", "1", 0); 47 | 48 | ComparerTest("1", "1", 0); 49 | 50 | ComparerTest("1", "10", -1); 51 | ComparerTest("10", "1", 1); 52 | 53 | ComparerTest("2", "10", -1); 54 | ComparerTest("10", "2", 1); 55 | } 56 | 57 | [Fact] 58 | public void CompareWithNumbersAndLetters() 59 | { 60 | ComparerTest("1", "a", -1); 61 | ComparerTest("a", "1", 1); 62 | 63 | ComparerTest("100", "a", -1); 64 | ComparerTest("a", "100", 1); 65 | } 66 | 67 | [Fact] 68 | public void CompareWithNonNumbers() 69 | { 70 | ComparerTest("1a", "100", 1); 71 | ComparerTest("100", "1a", -1); 72 | 73 | ComparerTest("100a", "100", 1); 74 | ComparerTest("100", "100a", -1); 75 | 76 | ComparerTest("a100", "100", 1); 77 | ComparerTest("100", "a100", -1); 78 | 79 | ComparerTest("1a", "a", -1); 80 | ComparerTest("a", "1a", 1); 81 | } 82 | 83 | [Fact] 84 | public void CompareIdenticalPaths() 85 | { 86 | ComparerTest("abc:DEF:0:a100", "ABC:DEF:0:a100", 0); 87 | } 88 | 89 | [Fact] 90 | public void CompareDifferentPaths() 91 | { 92 | ComparerTest("abc:def", "ghi:2", -1); 93 | ComparerTest("ghi:2", "abc:def", 1); 94 | } 95 | 96 | [Fact] 97 | public void ComparePathsWithCommonPart() 98 | { 99 | ComparerTest("abc:def:XYQ", "abc:def:XYZ", -1); 100 | ComparerTest("abc:def:XYZ", "abc:def:XYQ", 1); 101 | } 102 | 103 | [Fact] 104 | public void ComparePathsWithCommonPartButShorter() 105 | { 106 | ComparerTest("abc:def", "abc:def:ghi", -1); 107 | ComparerTest("abc:def:ghi", "abc:def", 1); 108 | } 109 | 110 | [Fact] 111 | public void ComparePathsWithIndicesAtTheEnd() 112 | { 113 | ComparerTest("abc:def:2", "abc:def:10", -1); 114 | ComparerTest("abc:def:10", "abc:def:2", 1); 115 | 116 | ComparerTest("abc:def:10", "abc:def:22", -1); 117 | ComparerTest("abc:def:22", "abc:def:10", 1); 118 | } 119 | 120 | [Fact] 121 | public void ComparePathsWithIndicesInside() 122 | { 123 | ComparerTest("abc:def:1000:jkl", "abc:def:ghi:jkl", -1); 124 | ComparerTest("abc:def:ghi:jkl", "abc:def:1000:jkl", 1); 125 | 126 | ComparerTest("abc:def:10:jkl", "abc:def:22:jkl", -1); 127 | ComparerTest("abc:def:22:jkl", "abc:def:10:jkl", 1); 128 | } 129 | 130 | private static void ComparerTest(string a, string b, int expectedSign) 131 | { 132 | var result = ConfigurationKeyComparer.Instance.Compare(a, b); 133 | Assert.Equal(expectedSign, Math.Sign(result)); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /test/Config.Test/ConfigurationPathTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Xunit; 6 | 7 | namespace Microsoft.Extensions.Configuration.Test 8 | { 9 | public class ConfigurationPathTest 10 | { 11 | [Fact] 12 | public void CombineWithEmptySegmentLeavesDelimiter() 13 | { 14 | Assert.Equal("parent:", ConfigurationPath.Combine("parent", "")); 15 | Assert.Equal("parent::", ConfigurationPath.Combine("parent", "", "")); 16 | Assert.Equal("parent:::key", ConfigurationPath.Combine("parent", "", "", "key")); 17 | } 18 | 19 | [Fact] 20 | public void GetLastSegmenGetSectionKeyTests() 21 | { 22 | Assert.Null(ConfigurationPath.GetSectionKey(null)); 23 | Assert.Equal("", ConfigurationPath.GetSectionKey("")); 24 | Assert.Equal("", ConfigurationPath.GetSectionKey(":::")); 25 | Assert.Equal("c", ConfigurationPath.GetSectionKey("a::b:::c")); 26 | Assert.Equal("", ConfigurationPath.GetSectionKey("a:::b:")); 27 | Assert.Equal("key", ConfigurationPath.GetSectionKey("key")); 28 | Assert.Equal("key", ConfigurationPath.GetSectionKey(":key")); 29 | Assert.Equal("key", ConfigurationPath.GetSectionKey("::key")); 30 | Assert.Equal("key", ConfigurationPath.GetSectionKey("parent:key")); 31 | } 32 | 33 | [Fact] 34 | public void GetParentPathTests() 35 | { 36 | Assert.Null(ConfigurationPath.GetParentPath(null)); 37 | Assert.Null(ConfigurationPath.GetParentPath("")); 38 | Assert.Equal("::", ConfigurationPath.GetParentPath(":::")); 39 | Assert.Equal("a::b::", ConfigurationPath.GetParentPath("a::b:::c")); 40 | Assert.Equal("a:::b", ConfigurationPath.GetParentPath("a:::b:")); 41 | Assert.Null(ConfigurationPath.GetParentPath("key")); 42 | Assert.Equal("", ConfigurationPath.GetParentPath(":key")); 43 | Assert.Equal(":", ConfigurationPath.GetParentPath("::key")); 44 | Assert.Equal("parent", ConfigurationPath.GetParentPath("parent:key")); 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/Config.UserSecrets.Test/Config.UserSecrets.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Microsoft.Extensions.Configuration.UserSecrets.Test 5 | Microsoft.Extensions.Configuration.UserSecrets.Test 6 | netcoreapp2.2 7 | 8 | 9 | 10 | 11 | 12 | 13 | <_Parameter1>TargetFramework 14 | <_Parameter2>$(TargetFramework) 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test/Config.UserSecrets.Test/PathHelperTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using System.Linq; 7 | using Xunit; 8 | 9 | namespace Microsoft.Extensions.Configuration.UserSecrets.Test 10 | { 11 | public class PathHelperTest 12 | { 13 | [Fact] 14 | public void Gives_Correct_Secret_Path() 15 | { 16 | var userSecretsId = "abcxyz123"; 17 | var actualSecretPath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); 18 | 19 | var root = Environment.GetEnvironmentVariable("APPDATA") ?? // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\ 20 | Environment.GetEnvironmentVariable("HOME"); // On Mac/Linux it goes to ~/.microsoft/usersecrets/ 21 | 22 | var expectedSecretPath = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPDATA")) ? 23 | Path.Combine(root, "Microsoft", "UserSecrets", userSecretsId, "secrets.json") : 24 | Path.Combine(root, ".microsoft", "usersecrets", userSecretsId, "secrets.json"); 25 | 26 | Assert.Equal(expectedSecretPath, actualSecretPath); 27 | } 28 | 29 | [Fact] 30 | public void Throws_If_UserSecretId_Contains_Invalid_Characters() 31 | { 32 | foreach (var character in Path.GetInvalidPathChars().Concat(Path.GetInvalidFileNameChars())) 33 | { 34 | var id = "Test" + character; 35 | Assert.Throws(() => PathHelper.GetSecretsPathFromSecretsId(id)); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/Config.Xml.Test/Config.Xml.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Microsoft.Extensions.Configuration.Xml.Test 5 | Microsoft.Extensions.Configuration.Xml.Test 6 | $(StandardTestTfms) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/Config.Xml.Test/XmlConfigurationExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using Xunit; 7 | 8 | namespace Microsoft.Extensions.Configuration.Xml.Test 9 | { 10 | public class XmlConfigurationExtensionsTest 11 | { 12 | [Fact] 13 | public void AddXmlFile_ThrowsIfFileDoesNotExistAtPath() 14 | { 15 | var config = new ConfigurationBuilder().AddXmlFile("NotExistingConfig.xml"); 16 | 17 | // Arrange 18 | // Act and Assert 19 | var ex = Assert.Throws(() => config.Build()); 20 | Assert.StartsWith($"The configuration file 'NotExistingConfig.xml' was not found and is not optional. The physical path is '", ex.Message); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | netcoreapp2.2 6 | $(DeveloperBuildTestTfms) 7 | 8 | $(StandardTestTfms);net461 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /version.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 3.0.0 4 | alpha1 5 | $(VersionPrefix) 6 | $(VersionPrefix)-$(VersionSuffix)-final 7 | t000 8 | a- 9 | $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) 10 | $(VersionSuffix)-$(BuildNumber) 11 | 12 | 13 | --------------------------------------------------------------------------------