如何在 ASP.Net Core 中使用 Consul 来存储配置(5)

private async Task<IDictionary<string, string>> ExecuteQueryAsync(bool isBlocking = false)
    {
        var requestUri = isBlocking ? $"?recurse=true&index={_consulConfigurationIndex}" : "?recurse=true";
        using (var request = new HttpRequestMessage(HttpMethod.Get, new Uri(_consulUrls[_consulUrlIndex], requestUri)))
        using (var response = await _httpClient.SendAsync(request))
        {
            response.EnsureSuccessStatusCode();
            if (response.Headers.Contains(ConsulIndexHeader))
            {
                var indexValue = response.Headers.GetValues(ConsulIndexHeader).FirstOrDefault();
                int.TryParse(indexValue, out _consulConfigurationIndex);
            }

var tokens = JToken.Parse(await response.Content.ReadAsStringAsync());
            return tokens
                .Select(k => KeyValuePair.Create
                    (
                        k.Value<string>("Key").Substring(_path.Length + 1),
                        k.Value<string>("Value") != null ? JToken.Parse(Encoding.UTF8.GetString(Convert.FromBase64String(k.Value<string>("Value")))) : null
                    ))
                .Where(v => !string.IsNullOrWhiteSpace(v.Key))
                .SelectMany(Flatten)
                .ToDictionary(v => ConfigurationPath.Combine(v.Key.Split('/')), v => v.Value, StringComparer.OrdinalIgnoreCase);
        }
    }

private static IEnumerable<KeyValuePair<string, string>> Flatten(KeyValuePair<string, JToken> tuple)
    {
        if (!(tuple.Value is JObject value))
            yield break;

foreach (var property in value)
        {
            var propertyKey = $"{tuple.Key}/{property.Key}";
            switch (property.Value.Type)
            {
                case JTokenType.Object:
                    foreach (var item in Flatten(KeyValuePair.Create(propertyKey, property.Value)))
                        yield return item;
                    break;
                case JTokenType.Array:
                    break;
                default:
                    yield return KeyValuePair.Create(propertyKey, property.Value.Value<string>());
                    break;
            }
        }
    }
}

组合在一起

我们现在有了一个 ConfigurationProvider, 让我们再写一个 ConfigurationSource 来创建 我们的 provider.

public class ConsulConfigurationSource : IConfigurationSource
{
    public IEnumerable<Uri> ConsulUrls { get; }
    public string Path { get; }

public ConsulConfigurationSource(IEnumerable<Uri> consulUrls, string path)
    {
        ConsulUrls = consulUrls;
        Path = path;
    }

public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new ConsulConfigurationProvider(ConsulUrls, Path);
    }
}

以及一些扩展方法 :

public static class ConsulConfigurationExtensions
{
    public static IConfigurationBuilder AddConsul(this IConfigurationBuilder configurationBuilder, IEnumerable<Uri> consulUrls, string consulPath)
    {
        return configurationBuilder.Add(new ConsulConfigurationSource(consulUrls, consulPath));
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/dc6dada1191ce973c790f42c47ceaf07.html