From 43cb1773265d0e041f0c1062251c32b193e98bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Tue, 18 May 2021 08:26:22 +0800 Subject: [PATCH] Add ConfigurationBuilder support (#105) * Add .ConfigureAwait(false) * Suppport ConfigurationBuilder * Add Nacos support ConfigurationBuilder * useGrpc --- .editorconfig | 49 +++++ Directory.Build.props | 21 +- nacos-sdk-csharp.sln | 26 ++- .../ConfigurationBuilderApp.csproj | 114 ++++++++++ samples/ConfigurationBuilderApp/Startup.cs | 31 +++ samples/ConfigurationBuilderApp/Web.config | 114 ++++++++++ .../DefaultJsonConfigurationStringParser.cs | 10 +- .../Impl/MsConfigServerHttpAgent.cs | 16 +- .../Impl/NacosMsConfigClient.cs | 2 +- .../ConfigListener.cs | 48 +++++ .../ConfigListenerCollection.cs | 39 ++++ .../Nacos.System.Configuration.csproj | 36 ++++ .../NacosConfigurationBuilder.cs | 203 ++++++++++++++++++ .../NacosConfigurationSection.cs | 76 +++++++ src/Nacos.System.Configuration/README.md | 9 + src/Nacos/Nacos.csproj | 2 +- 16 files changed, 768 insertions(+), 28 deletions(-) create mode 100644 .editorconfig create mode 100644 samples/ConfigurationBuilderApp/ConfigurationBuilderApp.csproj create mode 100644 samples/ConfigurationBuilderApp/Startup.cs create mode 100644 samples/ConfigurationBuilderApp/Web.config create mode 100644 src/Nacos.System.Configuration/ConfigListener.cs create mode 100644 src/Nacos.System.Configuration/ConfigListenerCollection.cs create mode 100644 src/Nacos.System.Configuration/Nacos.System.Configuration.csproj create mode 100644 src/Nacos.System.Configuration/NacosConfigurationBuilder.cs create mode 100644 src/Nacos.System.Configuration/NacosConfigurationSection.cs create mode 100644 src/Nacos.System.Configuration/README.md diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b1ca422 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,49 @@ +root = true + +[*] +charset = utf-8-bom +end_of_line = crlf +indent_size = 4 +indent_style = space +insert_final_newline = true +tab_width = 4 +trim_trailing_whitespace = true + +[.bowerrc|*.yml] +charset = utf-8 + +# Xml project files +[*.*proj] +indent_size = 2 + +# Xml build files +[*.builds] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset,xsd}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec,vsixmanifest,vsct}] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 + +# Shell scripts +[*.sh] +end_of_line = lf + +# ReSharper properties +resharper_csharp_wrap_lines=false +resharper_enforce_line_ending_style=true +resharper_js_wrap_lines=false +resharper_protobuf_wrap_lines=false +resharper_use_indent_from_vs=false +resharper_vb_wrap_lines=false +resharper_xmldoc_wrap_lines=false +resharper_xml_wrap_lines=false + + diff --git a/Directory.Build.props b/Directory.Build.props index 996295a..e3bd6ab 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,18 +1,16 @@ - - + latest git + + true + true + $(NoWarn),1573,1591,1712 + ..\..\_stylecop\codeanalysis.ruleset - - true - true - $(NoWarn),1573,1591,1712 - ..\..\_stylecop\codeanalysis.ruleset - - - + + @@ -20,4 +18,5 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - \ No newline at end of file + + diff --git a/nacos-sdk-csharp.sln b/nacos-sdk-csharp.sln index bf133fa..e0c75b4 100644 --- a/nacos-sdk-csharp.sln +++ b/nacos-sdk-csharp.sln @@ -31,9 +31,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.AspNetCore.Tests", "t EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "parsers", "parsers", "{CFFCAA8B-3562-420B-AA8B-C525CC1ECD78}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nacos.YamlParser", "parsers\Nacos.YamlParser\Nacos.YamlParser.csproj", "{94CF8EEE-3812-47C6-998F-9105EB092036}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.YamlParser", "parsers\Nacos.YamlParser\Nacos.YamlParser.csproj", "{94CF8EEE-3812-47C6-998F-9105EB092036}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nacos.IniParser", "parsers\Nacos.IniParser\Nacos.IniParser.csproj", "{CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.IniParser", "parsers\Nacos.IniParser\Nacos.IniParser.csproj", "{CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.System.Configuration", "src\Nacos.System.Configuration\Nacos.System.Configuration.csproj", "{7C20F5FB-33D4-460A-86F4-FC42122FA543}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfigurationBuilderApp", "samples\ConfigurationBuilderApp\ConfigurationBuilderApp.csproj", "{CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{81C1E3C0-6709-4726-A27D-C2346FAF39D7}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + Directory.Build.props = Directory.Build.props + README.md = README.md + README.zh-cn.md = README.zh-cn.md + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -89,6 +101,14 @@ Global {CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}.Debug|Any CPU.Build.0 = Debug|Any CPU {CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}.Release|Any CPU.ActiveCfg = Release|Any CPU {CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}.Release|Any CPU.Build.0 = Release|Any CPU + {7C20F5FB-33D4-460A-86F4-FC42122FA543}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C20F5FB-33D4-460A-86F4-FC42122FA543}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C20F5FB-33D4-460A-86F4-FC42122FA543}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C20F5FB-33D4-460A-86F4-FC42122FA543}.Release|Any CPU.Build.0 = Release|Any CPU + {CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -106,6 +126,8 @@ Global {F3DD367A-6EF5-4188-9D28-6858AA2F60F9} = {8176B7FC-151E-4EFF-A693-F60A39109595} {94CF8EEE-3812-47C6-998F-9105EB092036} = {CFFCAA8B-3562-420B-AA8B-C525CC1ECD78} {CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63} = {CFFCAA8B-3562-420B-AA8B-C525CC1ECD78} + {7C20F5FB-33D4-460A-86F4-FC42122FA543} = {C473C3A7-1B44-4E1F-83C0-745AD0566FE9} + {CA0A661F-01D5-4DF7-9CD0-0399F89A8D47} = {25B1A184-1541-4F4E-A151-24A47CC08F34} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A1C5215E-0E70-4C04-B21E-5209BCF32472} diff --git a/samples/ConfigurationBuilderApp/ConfigurationBuilderApp.csproj b/samples/ConfigurationBuilderApp/ConfigurationBuilderApp.csproj new file mode 100644 index 0000000..cd15f6d --- /dev/null +++ b/samples/ConfigurationBuilderApp/ConfigurationBuilderApp.csproj @@ -0,0 +1,114 @@ + + + + Debug + AnyCPU + + + 2.0 + {CA0A661F-01D5-4DF7-9CD0-0399F89A8D47} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + ConfigurationBuilderApp + ConfigurationBuilderApp + v4.7.1 + true + + + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + bin\ConfigurationBuilderApp.xml + + + true + pdbonly + true + bin\ + TRACE + prompt + 4 + bin\ConfigurationBuilderApp.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {7c20f5fb-33d4-460a-86f4-fc42122fa543} + Nacos.System.Configuration + + + + + 4.2.0 + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + true + + + + + + + + + True + True + 12012 + / + http://localhost:12012/ + False + False + + + False + + + + + + \ No newline at end of file diff --git a/samples/ConfigurationBuilderApp/Startup.cs b/samples/ConfigurationBuilderApp/Startup.cs new file mode 100644 index 0000000..5fac4a4 --- /dev/null +++ b/samples/ConfigurationBuilderApp/Startup.cs @@ -0,0 +1,31 @@ +using ConfigurationBuilderApp; +using Microsoft.Owin; +using Owin; +using System.Configuration; +using System.Threading.Tasks; + +[assembly: OwinStartup(typeof(Startup))] + +namespace ConfigurationBuilderApp +{ + public class Startup + { + public void Configuration(IAppBuilder app) + { + app.Run(context => + { + context.Response.StatusCode = 404; + + var key = context.Request.Query["key"]; + if (string.IsNullOrWhiteSpace(key)) return Task.CompletedTask; + + var value = ConfigurationManager.AppSettings[key]; + if (value != null) context.Response.StatusCode = 200; + + context.Response.Headers["Content-Type"] = "text/html; charset=utf-8"; + + return context.Response.WriteAsync(value ?? "undefined"); + }); + } + } +} diff --git a/samples/ConfigurationBuilderApp/Web.config b/samples/ConfigurationBuilderApp/Web.config new file mode 100644 index 0000000..3b7a58b --- /dev/null +++ b/samples/ConfigurationBuilderApp/Web.config @@ -0,0 +1,114 @@ + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Nacos.Microsoft.Extensions.Configuration/DefaultJsonConfigurationStringParser.cs b/src/Nacos.Microsoft.Extensions.Configuration/DefaultJsonConfigurationStringParser.cs index bb136d9..39747ba 100644 --- a/src/Nacos.Microsoft.Extensions.Configuration/DefaultJsonConfigurationStringParser.cs +++ b/src/Nacos.Microsoft.Extensions.Configuration/DefaultJsonConfigurationStringParser.cs @@ -6,11 +6,11 @@ namespace Nacos.Microsoft.Extensions.Configuration using Nacos.Config; using Newtonsoft.Json; using Newtonsoft.Json.Linq; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Linq; + using global::System; + using global::System.Collections.Generic; + using global::System.Globalization; + using global::System.IO; + using global::System.Linq; internal class DefaultJsonConfigurationStringParser : INacosConfigurationParser { diff --git a/src/Nacos.Microsoft.Extensions.Configuration/Impl/MsConfigServerHttpAgent.cs b/src/Nacos.Microsoft.Extensions.Configuration/Impl/MsConfigServerHttpAgent.cs index 728b8d9..dead66a 100644 --- a/src/Nacos.Microsoft.Extensions.Configuration/Impl/MsConfigServerHttpAgent.cs +++ b/src/Nacos.Microsoft.Extensions.Configuration/Impl/MsConfigServerHttpAgent.cs @@ -1,16 +1,16 @@ namespace Nacos.Microsoft.Extensions.Configuration { + using global::System; + using global::System.Collections.Generic; + using global::System.Diagnostics; + using global::System.Linq; + using global::System.Net; + using global::System.Net.Http; + using global::System.Threading; + using global::System.Threading.Tasks; using Nacos.Config; using Nacos.Config.Http; using Nacos.Security; - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Net; - using System.Net.Http; - using System.Threading; - using System.Threading.Tasks; public class MsConfigServerHttpAgent : HttpAgent, IDisposable { diff --git a/src/Nacos.Microsoft.Extensions.Configuration/Impl/NacosMsConfigClient.cs b/src/Nacos.Microsoft.Extensions.Configuration/Impl/NacosMsConfigClient.cs index 8a08c26..e1fe226 100644 --- a/src/Nacos.Microsoft.Extensions.Configuration/Impl/NacosMsConfigClient.cs +++ b/src/Nacos.Microsoft.Extensions.Configuration/Impl/NacosMsConfigClient.cs @@ -1,9 +1,9 @@ namespace Nacos.Microsoft.Extensions.Configuration { using global::Microsoft.Extensions.Logging; + using global::System.Collections.Generic; using Nacos; using Nacos.Config.Http; - using System.Collections.Generic; public class NacosMsConfigClient : AbstNacosConfigClient { diff --git a/src/Nacos.System.Configuration/ConfigListener.cs b/src/Nacos.System.Configuration/ConfigListener.cs new file mode 100644 index 0000000..2f0f898 --- /dev/null +++ b/src/Nacos.System.Configuration/ConfigListener.cs @@ -0,0 +1,48 @@ +namespace Nacos.System.Configuration +{ + using global::System; + using global::System.Configuration; + using Nacos.Config; + using Nacos.Microsoft.Extensions.Configuration; + + public class ConfigListener : ConfigurationSection + { + /// + /// Configuration ID + /// + [ConfigurationProperty("dataId", IsRequired = false)] + public string DataId => this["dataId"]?.ToString(); + + /// + /// Configuration group + /// + [ConfigurationProperty("group", DefaultValue = "DEFAULT_GROUP", IsRequired = false)] + public string Group => this["group"]?.ToString(); + + [ConfigurationProperty("parserType", IsRequired = false)] + public string ParserType => this["parserType"] as string; + + /// + /// The configuration parser, default is json + /// + public INacosConfigurationParser NacosConfigurationParser + { + get + { + _parser ??= new Lazy(() => + { + if (string.IsNullOrWhiteSpace(ParserType)) return null; + + var type = Type.GetType(ParserType); + if (type == null) throw new TypeLoadException("不能找到类型" + ParserType); + + return (INacosConfigurationParser)Activator.CreateInstance(type); + }); + + return _parser.Value ?? DefaultJsonConfigurationStringParser.Instance; + } + } + + private Lazy _parser; + } +} diff --git a/src/Nacos.System.Configuration/ConfigListenerCollection.cs b/src/Nacos.System.Configuration/ConfigListenerCollection.cs new file mode 100644 index 0000000..8545d4b --- /dev/null +++ b/src/Nacos.System.Configuration/ConfigListenerCollection.cs @@ -0,0 +1,39 @@ +namespace Nacos.System.Configuration +{ + using global::System.Configuration; + + public class ConfigListenerCollection : ConfigurationElementCollection + { + public ConfigListenerCollection() => AddElementName = "listener"; + + /// + /// Gets or sets the at the specified index. + /// + /// + /// The . + /// + /// The index. + public ConfigListener this[int index] + { + get => BaseGet(index) as ConfigListener; + set + { + if (BaseGet(index) != null) BaseRemoveAt(index); + + BaseAdd(index, value); + } + } + + /// + /// Creates the new element. + /// + protected override ConfigurationElement CreateNewElement() => new ConfigListener(); + + /// + /// Gets the element key. + /// + /// The element. + protected override object GetElementKey(ConfigurationElement element) + => $"{((ConfigListener)element).Group}#{((ConfigListener)element).DataId}"; + } +} \ No newline at end of file diff --git a/src/Nacos.System.Configuration/Nacos.System.Configuration.csproj b/src/Nacos.System.Configuration/Nacos.System.Configuration.csproj new file mode 100644 index 0000000..7e69641 --- /dev/null +++ b/src/Nacos.System.Configuration/Nacos.System.Configuration.csproj @@ -0,0 +1,36 @@ + + + + + net471 + nacos-sdk-csharp.ConfigurationManger + $(NugetVersion) + + nacos-sdk-csharp Contributors + nacos csharp sdk + nacos,csharp,sdk,msconfig,ConfigurationBuilder + https://github.com/nacos-group/nacos-sdk-csharp + https://github.com/nacos-group/nacos-sdk-csharp + https://github.com/nacos-group/nacos-sdk-csharp + LICENSE + + + + true + $(NoWarn);1591 + + + + + + + + + + + + + + + + diff --git a/src/Nacos.System.Configuration/NacosConfigurationBuilder.cs b/src/Nacos.System.Configuration/NacosConfigurationBuilder.cs new file mode 100644 index 0000000..7061c78 --- /dev/null +++ b/src/Nacos.System.Configuration/NacosConfigurationBuilder.cs @@ -0,0 +1,203 @@ +namespace Nacos.System.Configuration +{ + using global::Microsoft.Configuration.ConfigurationBuilders; + using global::Microsoft.Extensions.Logging; + using global::Microsoft.Extensions.Logging.Abstractions; + using global::Microsoft.Extensions.Options; + using global::System; + using global::System.Collections.Concurrent; + using global::System.Collections.Generic; + using global::System.Collections.Specialized; + using global::System.Configuration; + using global::System.Diagnostics; + using global::System.Linq; + using global::System.Reflection; + using global::System.Threading.Tasks; + using Nacos.Microsoft.Extensions.Configuration; + using Nacos.V2; + using Nacos.V2.Config; + + public class NacosConfigurationBuilder : KeyValueConfigBuilder + { + public static ILoggerFactory LoggerFactory { get; set; } + + private static readonly FieldInfo ConfigurationManagerReset = typeof(ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static)!; + private static readonly Dictionary> ClientCache = new Dictionary>(StringComparer.OrdinalIgnoreCase); + private static readonly ConcurrentDictionary ConfigCache = new ConcurrentDictionary(); + + private Task[]> _data; + + public override void Initialize(string name, NameValueCollection config) + { + config ??= new NameValueCollection(); + + if (config["mode"] == null) + { + config["mode"] = nameof(KeyValueMode.Greedy); + } + + base.Initialize(name, config); + } + + protected override void LazyInitialize(string name, NameValueCollection config) + { + base.LazyInitialize(name, config); + + var sectionName = string.IsNullOrWhiteSpace(config["nacosConfig"]) ? "nacos" : config["nacosConfig"]; + if (!ClientCache.TryGetValue(sectionName, out var cache)) + { + lock (ClientCache) + { + if (!ClientCache.TryGetValue(sectionName, out cache)) + { + var nacosConfig = NacosConfigurationSection.GetConfig(sectionName); + if (nacosConfig == null) + { + LoggerFactory?.CreateLogger().LogWarning($"Can't found `{sectionName}` config"); + + Trace.TraceWarning($"Can't found `{sectionName}` config"); + + ClientCache[sectionName] = null; + + return; + } + + if (nacosConfig.UseGrpc) + { + var client = new NacosConfigService(LoggerFactory ?? NullLoggerFactory.Instance, Options.Create(new NacosSdkOptions + { + ServerAddresses = nacosConfig.ServerAddresses.Split(';', ',').ToList(), + Namespace = nacosConfig.Tenant, + AccessKey = nacosConfig.AccessKey, + ContextPath = nacosConfig.ContextPath, + EndPoint = nacosConfig.EndPoint, + DefaultTimeOut = nacosConfig.DefaultTimeOut, + SecretKey = nacosConfig.SecretKey, + Password = nacosConfig.Password, + UserName = nacosConfig.UserName, + ListenInterval = 20000 + })); + + ClientCache[sectionName] = cache = Tuple.Create(nacosConfig, (object)client); + } + else + { + var client = new NacosMsConfigClient(LoggerFactory ?? NullLoggerFactory.Instance, new NacosOptions + { + ServerAddresses = nacosConfig.ServerAddresses.Split(';', ',').ToList(), + Namespace = nacosConfig.Tenant, + AccessKey = nacosConfig.AccessKey, + ClusterName = nacosConfig.ClusterName, + ContextPath = nacosConfig.ContextPath, + EndPoint = nacosConfig.EndPoint, + DefaultTimeOut = nacosConfig.DefaultTimeOut, + SecretKey = nacosConfig.SecretKey, + Password = nacosConfig.Password, + UserName = nacosConfig.UserName, + ListenInterval = 20000 + }); + + ClientCache[sectionName] = cache = Tuple.Create(nacosConfig, (object)client); + } + + if (nacosConfig.Listeners != null && nacosConfig.Listeners.Count > 0) + { + try + { + _ = Task.WhenAll(nacosConfig.Listeners + .OfType() + .Select(item => cache.Item2 is INacosConfigClient ncc + ? ncc.AddListenerAsync(new AddListenerRequest + { + DataId = item.DataId, + Group = item.Group, + Tenant = nacosConfig.Tenant, + Callbacks = new List> { x => CallBackReload($"{nacosConfig.Tenant}#{item.Group}#{item.DataId}", x) } + }) + : ((INacosConfigService)cache.Item2).AddListener(item.DataId, item.Group ?? ConstValue.DefaultGroup, new MsConfigListener($"{nacosConfig.Tenant}#{item.Group}#{item.DataId}")))); + } + catch (Exception ex) + { + LoggerFactory?.CreateLogger().LogError(ex, "AddListener fail."); + + Trace.TraceError("AddListener fail" + Environment.NewLine + ex); + } + } + } + } + } + + _data = cache == null ? Task.FromResult(Array.Empty>()) : GetConfig(cache.Item1, cache.Item2); + } + + private static Task[]> GetConfig(NacosConfigurationSection config, object client) => + Task.WhenAll(config.Listeners.OfType() + .Select(async item => + { + if (!ConfigCache.TryGetValue($"{config.Tenant}#{item.Group}#{item.DataId}", out var data)) + { + try + { + data = await (client is INacosConfigClient ncc + ? ncc.GetConfigAsync(new GetConfigRequest + { + DataId = item.DataId, + Group = item.Group, + Tenant = config.Tenant + }) + : ((INacosConfigService)client).GetConfig(item.DataId, item.Group ?? ConstValue.DefaultGroup, 3000)) + .ConfigureAwait(false); + + if (data == null) + { + LoggerFactory?.CreateLogger().LogWarning($"Can't get config {item.Group}#{item.DataId}"); + } + } + catch (Exception ex) + { + LoggerFactory?.CreateLogger().LogError(ex, $"GetConfig({item.Group}#{item.DataId}) fail."); + + Trace.TraceError($"GetConfig({item.Group}#{item.DataId}) fail" + Environment.NewLine + ex); + } + } + + return data == null ? new Dictionary() : item.NacosConfigurationParser.Parse(data); + })); + + private static void CallBackReload(string key, string data) + { + ConfigCache[key] = data; + + try + { + ConfigurationManagerReset.SetValue(null, 0); + } + catch + { + // ignored + } + } + + public override string GetValue(string key) + { + foreach (var dic in _data.GetAwaiter().GetResult()) + { + if (dic.TryGetValue(key, out var value)) return value; + } + + return null; + } + + public override ICollection> GetAllValues(string prefix) => + _data.GetAwaiter().GetResult().SelectMany(dic => dic).ToArray(); + + private class MsConfigListener : IListener + { + private readonly string _key; + + public MsConfigListener(string key) => _key = key; + + public void ReceiveConfigInfo(string configInfo) => CallBackReload(_key, configInfo); + } + } +} diff --git a/src/Nacos.System.Configuration/NacosConfigurationSection.cs b/src/Nacos.System.Configuration/NacosConfigurationSection.cs new file mode 100644 index 0000000..2611594 --- /dev/null +++ b/src/Nacos.System.Configuration/NacosConfigurationSection.cs @@ -0,0 +1,76 @@ +namespace Nacos.System.Configuration +{ + using global::System; + using global::System.Configuration; + + public class NacosConfigurationSection : ConfigurationSection + { + /// + /// Nacos Server Addresses + /// + [ConfigurationProperty("serverAddresses", IsRequired = true)] + public string ServerAddresses => this["serverAddresses"].ToString(); + + /// + /// The configuration listeners + /// + [ConfigurationProperty("listeners", IsRequired = true)] + public ConfigListenerCollection Listeners => this["listeners"] as ConfigListenerCollection; + + /// + /// Tenant information. It corresponds to the Namespace field in Nacos. + /// + [ConfigurationProperty("tenant", IsRequired = true)] + public string Tenant => this["tenant"]?.ToString(); + + /// + /// EndPoint + /// + [ConfigurationProperty("endPoint", IsRequired = false)] + public string EndPoint => this["endPoint"]?.ToString(); + + [ConfigurationProperty("contextPath", DefaultValue = "nacos")] + public string ContextPath => this["contextPath"]?.ToString(); + + [ConfigurationProperty("clusterName", DefaultValue = "serverlist")] + public string ClusterName => this["clusterName"]?.ToString(); + + /// + /// default timeout, unit is Milliseconds. + /// + [ConfigurationProperty("defaultTimeOut", DefaultValue = 15000)] + public int DefaultTimeOut => Convert.ToInt32(this["defaultTimeOut"]); + + /// + /// accessKey + /// + [ConfigurationProperty("accessKey")] + public string AccessKey => this["accessKey"]?.ToString(); + + /// + /// secretKey + /// + [ConfigurationProperty("secretKey")] + public string SecretKey => this["secretKey"]?.ToString(); + + /// + /// useGrpc + /// + [ConfigurationProperty("useGrpc", DefaultValue = false)] + public bool UseGrpc => Convert.ToBoolean(this["useGrpc"]); + + /// + /// username + /// + [ConfigurationProperty("userName", IsRequired = true)] + public string UserName => this["userName"]?.ToString(); + + /// + /// password + /// + [ConfigurationProperty("password", IsRequired = true)] + public string Password => this["password"]?.ToString(); + + public static NacosConfigurationSection GetConfig(string sectionName) => ConfigurationManager.GetSection(string.IsNullOrWhiteSpace(sectionName) ? "nacos" : sectionName) as NacosConfigurationSection; + } +} diff --git a/src/Nacos.System.Configuration/README.md b/src/Nacos.System.Configuration/README.md new file mode 100644 index 0000000..7b1de57 --- /dev/null +++ b/src/Nacos.System.Configuration/README.md @@ -0,0 +1,9 @@ +# [ConfigurationBuilder](https://github.com/aspnet/MicrosoftConfigurationBuilders#implementing-more-keyvalue-config-builders) of nacos + +## NacosConfigurationBuilder property +* mode default value is Greedy +* nacosConfig default value is nacos +* more property please see [MicrosoftConfigurationBuilders](https://github.com/aspnet/MicrosoftConfigurationBuilders) + +## sample +[ConfigurationBuilderApp](https://github.com/nacos-group/nacos-sdk-csharp/tree/dev/samples/ConfigurationBuilderApp/web.config) \ No newline at end of file diff --git a/src/Nacos/Nacos.csproj b/src/Nacos/Nacos.csproj index 04f8ce4..0b36f66 100644 --- a/src/Nacos/Nacos.csproj +++ b/src/Nacos/Nacos.csproj @@ -39,7 +39,7 @@ - +