protected virtual IConfigurationRoot LoadAppConfiguration(Xml.AppInfo appInfo, PathMap appPathMap)
        {
            var builder = new ConfigurationBuilder();

            foreach (var configuration in appInfo.ConfigurationFiles)
            {
                if (configuration.Environment != null && !configuration.Environment.Equals(this.EnvName, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                if (configuration is ConfigurationEnvironmentVariablesElement environmentVariablesConfiguration)
                {
                    builder.Add(new EnvironmentVariablesConfigurationSource()
                    {
                        Prefix = environmentVariablesConfiguration.Prefix,
                    });
                }
                else if (configuration is ConfigurationFileElement fileConfiguration)
                {
                    var loaded = false;
                    foreach (var configPath in appPathMap.Compile(fileConfiguration.Path))
                    {
                        if (File.Exists(configPath))
                        {
                            try
                            {
                                FileConfigurationSource source;
                                switch (fileConfiguration.Type)
                                {
                                case "ini": source = new IniConfigurationSource(); break;

                                case "xml": source = new XmlConfigurationSource(); break;

                                case "json": source = new JsonConfigurationSource(); break;

                                default: throw new Exception("Unknown configuration type.");
                                }

                                source.FileProvider   = new PhysicalFileProvider(Path.GetDirectoryName(configPath));
                                source.Path           = Path.GetFileName(configPath);
                                source.ReloadOnChange = fileConfiguration.ReloadOnChange;

                                builder.Add(source);
                            }
                            catch (Exception exception)
                            {
                                throw new Exception($"Can not read configuration file \"{configPath}\": {exception.Message}", exception);
                            }

                            loaded = true;
                            break;
                        }
                    }

                    if (!fileConfiguration.Optional && !loaded)
                    {
                        throw new Exception($"Can not find required configuration file \"{fileConfiguration.Path}\".");
                    }
                }
            }

            return(builder.Build());
        }