From 46e4bbef25c5165001f2e8e9acbef6383dabb192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Thu, 18 Nov 2021 20:01:07 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0CommonConfigurationBuilde?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apollo.ConfigurationManager.Tests/App.config | 10 + .../ConfigurationBuilderTest.cs | 37 +++- .../TestConfigurationSection.cs | 21 +++ .../Apollo.ConfigurationManager.csproj | 2 +- .../CommonConfigurationBuilder.cs | 171 ++++++++++++++++++ Apollo.ConfigurationManager/README.md | 52 +++++- 6 files changed, 285 insertions(+), 8 deletions(-) create mode 100644 Apollo.ConfigurationManager.Tests/TestConfigurationSection.cs create mode 100644 Apollo.ConfigurationManager/CommonConfigurationBuilder.cs diff --git a/Apollo.ConfigurationManager.Tests/App.config b/Apollo.ConfigurationManager.Tests/App.config index 6462a34..8363c01 100644 --- a/Apollo.ConfigurationManager.Tests/App.config +++ b/Apollo.ConfigurationManager.Tests/App.config @@ -3,22 +3,32 @@
+
+ + + + + + + + + diff --git a/Apollo.ConfigurationManager.Tests/ConfigurationBuilderTest.cs b/Apollo.ConfigurationManager.Tests/ConfigurationBuilderTest.cs index 5da7ebb..a4b3124 100644 --- a/Apollo.ConfigurationManager.Tests/ConfigurationBuilderTest.cs +++ b/Apollo.ConfigurationManager.Tests/ConfigurationBuilderTest.cs @@ -26,5 +26,40 @@ public void NodeReplaceSectionBuilderTest() Assert.Equal(new Uri("http://localhost:1234"), endpoint.Address); Assert.Equal("test", endpoint.Name); } + + [Fact] + public void CommonConfigurationBuilderTest() + { + var test = (TestConfigurationSection)System.Configuration.ConfigurationManager.GetSection("test"); + + Assert.Equal(3, test.DefaultValue); + + Assert.Equal(TimeSpan.FromSeconds(30), test.Timeout); + + Assert.Equal(100, test.MaxValue); + + Assert.NotNull(test.Map); + + var element = test.Map["abc"]; + + Assert.NotNull(element); + + Assert.Equal("abc", element.Key); + Assert.Equal("123", element.Value); + + Assert.Null(test.Map["def"]); + + element = test.Map["defg"]; + + Assert.NotNull(element); + + Assert.Equal("defg", element.Key); + Assert.Equal("456", element.Value); + + Assert.NotNull(test.Element); + + Assert.Equal("jkl", test.Element.Name); + Assert.Equal("789", test.Element.Value); + } #endif -} \ No newline at end of file +} diff --git a/Apollo.ConfigurationManager.Tests/TestConfigurationSection.cs b/Apollo.ConfigurationManager.Tests/TestConfigurationSection.cs new file mode 100644 index 0000000..c772686 --- /dev/null +++ b/Apollo.ConfigurationManager.Tests/TestConfigurationSection.cs @@ -0,0 +1,21 @@ +using System.Configuration; + +namespace Apollo.ConfigurationManager.Tests; + +public class TestConfigurationSection : ConfigurationSection +{ + [ConfigurationProperty("timeout")] + public TimeSpan Timeout => (TimeSpan)this["timeout"]; + + [ConfigurationProperty("maxValue")] + public int MaxValue => (int)this["maxValue"]; + + [ConfigurationProperty("defaultValue", DefaultValue = 3L)] + public long DefaultValue => (long)this["defaultValue"]; + + [ConfigurationProperty("element")] + public NameValueConfigurationElement Element => (NameValueConfigurationElement)this["element"]; + + [ConfigurationProperty("", IsDefaultCollection = true)] + public KeyValueConfigurationCollection Map => (KeyValueConfigurationCollection)this[""]; +} diff --git a/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj b/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj index 9e7380d..2482aa5 100644 --- a/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj +++ b/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj @@ -16,7 +16,7 @@ $(PackageReleaseNotes) $(PackageTags) ConfigurationBuilder ConfigurationManager Com.Ctrip.Framework.Apollo net471;net45;net40;netstandard2.0;netstandard2.1 - $(ApolloVersion) + $(ApolloVersion).1 diff --git a/Apollo.ConfigurationManager/CommonConfigurationBuilder.cs b/Apollo.ConfigurationManager/CommonConfigurationBuilder.cs new file mode 100644 index 0000000..6cf4474 --- /dev/null +++ b/Apollo.ConfigurationManager/CommonConfigurationBuilder.cs @@ -0,0 +1,171 @@ +using System.Configuration; +using System.Linq.Expressions; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.ExceptionServices; +using static Com.Ctrip.Framework.Apollo.ConfigExtensions; + +namespace Com.Ctrip.Framework.Apollo; + +public class CommonConfigurationBuilder : ApolloConfigurationBuilder +{ + private static readonly Action Add; + private static readonly Func CreateNewElement; + private static readonly Action SetValue; + private string? _keyPrefix; + + static CommonConfigurationBuilder() + { + var set = typeof(ConfigurationElement).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .First(p => + { + var ip = p.GetIndexParameters(); + + return ip.Length == 1 && ip[0].ParameterType == typeof(ConfigurationProperty); + }) + .SetMethod; + + var convertFromString = typeof(ConfigurationProperty).GetMethod("ConvertFromString", BindingFlags.Instance | BindingFlags.NonPublic)!; + + var createNewElement = typeof(ConfigurationElementCollection).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .First(m => m.Name == nameof(CreateNewElement) && m.GetParameters().Length == 0); + + var param0 = Expression.Parameter(typeof(ConfigurationElementCollection)); + var param1 = Expression.Parameter(typeof(ConfigurationElement)); + var param2 = Expression.Parameter(typeof(ConfigurationProperty)); + var param3 = Expression.Parameter(typeof(string)); + + Add = CreateAddMethod(); + + CreateNewElement = Expression.Lambda>( + Expression.Call(param0, createNewElement), param0).Compile(); + + SetValue = Expression.Lambda>( + Expression.Call(param1, set, param2, Expression.Call(param2, convertFromString, param3)), + param1, param2, param3).Compile(); + } + + public override void Initialize(string name, NameValueCollection config) + { + base.Initialize(name, config); + + _keyPrefix = config["keyPrefix"]; + } + + public override ConfigurationSection ProcessConfigurationSection(ConfigurationSection configSection) + { + Bind(configSection, GetConfig(), string.IsNullOrEmpty(_keyPrefix) + ? new ConfigKey(configSection.SectionInformation.SectionName, configSection.SectionInformation.SectionName) + : new ConfigKey(_keyPrefix!.Substring(_keyPrefix!.LastIndexOf(':') + 1), _keyPrefix)); + + return configSection; + } + + private static void Bind(ConfigurationElement configElement, IConfig config, ConfigKey configKey) + { + foreach (var property in configElement.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + { + var cpa = property.GetCustomAttribute(); + if (cpa == null) continue; + + var key = $"{configKey.FullName}:{cpa.Name}"; + + if (typeof(ConfigurationElement).IsAssignableFrom(property.PropertyType)) + { + var element = property.GetValue(configElement); + if (element == null) property.SetValue(configElement, element = Activator.CreateInstance(property.PropertyType)); + + if (element is ConfigurationElementCollection cec) + { + foreach (var child in config.GetChildren(key)) + { + var ele = CreateNewElement(cec); + + Bind(ele, config, child); + + Add(cec, ele); + } + } + else if (element is ConfigurationElement ce) Bind(ce, config, new ConfigKey(cpa.Name, key)); + } + else + { + var cp = new ConfigurationProperty(cpa.Name, property.PropertyType, cpa.DefaultValue, cpa.Options); + + ExceptionDispatchInfo? ex = null; + + if (cpa.IsKey) + try + { + SetValue(configElement, cp, configKey.Name); + } + catch (ConfigurationErrorsException e) + { + ex = ExceptionDispatchInfo.Capture(e); + } + else if (string.Equals("value", cpa.Name, StringComparison.OrdinalIgnoreCase) && + config.TryGetProperty(configKey.FullName, out var value)) + try + { + SetValue(configElement, cp, value); + } + catch (ConfigurationErrorsException e) + { + ex = ExceptionDispatchInfo.Capture(e); + } + + if (ex == null) + { + if (config.TryGetProperty(key, out var value)) + SetValue(configElement, cp, value); + } + else if (config.TryGetProperty(key, out var value)) + SetValue(configElement, cp, value); + else ex.Throw(); + } + } + } + + private static Action CreateAddMethod() + { + var methods = typeof(ConfigurationElementCollection) + .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + + MethodInfo GetMethod(string method, params Type[] parameterTypes) + { + var ms = methods!.Where(m => m.Name == method).ToArray(); + if (parameterTypes.Length < 1) return ms.FirstOrDefault(m => m.GetParameters().Length == 0) ?? ms.First(); + + return ms.First(m => + { + var p = m.GetParameters(); + + if (p.Length != parameterTypes.Length) return false; + + return !p.Where((t, index) => t.ParameterType != parameterTypes[index]).Any(); + }); + } + + var method = new DynamicMethod("Add", typeof(void), + new[] { typeof(ConfigurationElementCollection), typeof(ConfigurationElement) }, + typeof(CommonConfigurationBuilder).Module, true); + + var il = method.GetILGenerator(); + + //BaseRemove(GetElementKey(element)); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Callvirt, GetMethod("GetElementKey")); + il.Emit(OpCodes.Call, GetMethod("BaseRemove", typeof(object))); + + //BaseAdd(element); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Callvirt, GetMethod("BaseAdd", typeof(ConfigurationElement))); + + il.Emit(OpCodes.Ret); + + return (Action)method.CreateDelegate(typeof(Action)); + } +} diff --git a/Apollo.ConfigurationManager/README.md b/Apollo.ConfigurationManager/README.md index 5bc2376..3b6eda7 100644 --- a/Apollo.ConfigurationManager/README.md +++ b/Apollo.ConfigurationManager/README.md @@ -194,7 +194,7 @@ apollo.net项目中有多个样例客户端的项目: # 四、NETFramework 4.7.1+ ConfigurationBuilder支持 -## 4.1 ApolloConfigurationBuilder说明 +## 4.1 ApolloConfigurationBuilder ``` xml @@ -203,27 +203,67 @@ apollo.net项目中有多个样例客户端的项目: - ``` * namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 -## 4.2 ConnectionStringsSectionBuilder使用说明 +## 4.2 ConnectionStringsSectionBuilder ``` xml - + - ``` * namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 * defaultProviderName为可选值,默认值为System.Data.SqlClient,,对应ConnectionString的ProviderName。 -* key必须以ConnectionStrings:开始 +* keyPrefix为可选值,默认值是connectionStrings * 通过ConnectionStrings:ConnectionName:ConnectionString或者ConnectionStrings:ConnectionName来设置连接字符串(同时指定时ConnectionStrings:ConnectionName:ConnectionString优先级高) * 通过ConnectionStrings:ConnectionName:ProviderName来指定使用其他数据库,比如MySql.Data.MySqlClient来指定是MySql +## 4.3 CommonConfigurationBuilder +通过反射结点类型,动态递归添加到节点类型中,此方法灵活,适应绝大部分节点。 +``` xml + + + + + + + +``` +* namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 +* keyPrefix为可选值,默认是以节点名 + +## 4.4 Key2XmlConfigurationBuilder +通过简单的层次结构改换成xml,限制比较大,建议使用CommonConfigurationBuilder。 +``` xml + + + + + + + +``` +* namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 +* keyPrefix为可选值,默认是以节点名 + +## 4.5 NodeReplaceSectionBuilder +直接使用apollo中配置的xml替换掉原来的节点xml +``` xml + + + + + + + +``` +* namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 +* key为可选值,默认是以节点名 + # 五、FAQ ## 5.1 Apollo内部HttpClient如何配置代理 From 559580377655dfbd3b9740ab2d99417cc9a1de09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Thu, 18 Nov 2021 20:10:17 +0800 Subject: [PATCH 2/4] CommonConfigurationBuilder => CommonSectionBuilder --- Apollo.ConfigurationManager.Tests/App.config | 4 ++-- .../Apollo.ConfigurationManager.csproj | 1 - ...tionBuilder.cs => CommonSectionBuilder.cs} | 6 ++--- .../Key2XmlConfigurationBuilder.cs | 22 ----------------- Apollo.ConfigurationManager/README.md | 24 ++++--------------- 5 files changed, 10 insertions(+), 47 deletions(-) rename Apollo.ConfigurationManager/{CommonConfigurationBuilder.cs => CommonSectionBuilder.cs} (97%) delete mode 100644 Apollo.ConfigurationManager/Key2XmlConfigurationBuilder.cs diff --git a/Apollo.ConfigurationManager.Tests/App.config b/Apollo.ConfigurationManager.Tests/App.config index 8363c01..0018bd9 100644 --- a/Apollo.ConfigurationManager.Tests/App.config +++ b/Apollo.ConfigurationManager.Tests/App.config @@ -11,7 +11,7 @@ - + @@ -27,7 +27,7 @@ - + diff --git a/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj b/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj index 2482aa5..39f901f 100644 --- a/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj +++ b/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj @@ -11,7 +11,6 @@   直接使用ApolloConfigurationManager请使用Com.Ctrip.Framework.Apollo.Configuration或者Com.Ctrip.Framework.Apollo.ConfigurationManager $(PackageReleaseNotes) - https://raw.githubusercontent.com/apolloconfig/apollo/master/apollo-portal/src/main/resources/static/img/config.png $(RepositoryUrl)/$(MSBuildProjectName) $(PackageTags) ConfigurationBuilder ConfigurationManager Com.Ctrip.Framework.Apollo diff --git a/Apollo.ConfigurationManager/CommonConfigurationBuilder.cs b/Apollo.ConfigurationManager/CommonSectionBuilder.cs similarity index 97% rename from Apollo.ConfigurationManager/CommonConfigurationBuilder.cs rename to Apollo.ConfigurationManager/CommonSectionBuilder.cs index 6cf4474..412a3cc 100644 --- a/Apollo.ConfigurationManager/CommonConfigurationBuilder.cs +++ b/Apollo.ConfigurationManager/CommonSectionBuilder.cs @@ -7,14 +7,14 @@ namespace Com.Ctrip.Framework.Apollo; -public class CommonConfigurationBuilder : ApolloConfigurationBuilder +public class CommonSectionBuilder : ApolloConfigurationBuilder { private static readonly Action Add; private static readonly Func CreateNewElement; private static readonly Action SetValue; private string? _keyPrefix; - static CommonConfigurationBuilder() + static CommonSectionBuilder() { var set = typeof(ConfigurationElement).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .First(p => @@ -148,7 +148,7 @@ MethodInfo GetMethod(string method, params Type[] parameterTypes) var method = new DynamicMethod("Add", typeof(void), new[] { typeof(ConfigurationElementCollection), typeof(ConfigurationElement) }, - typeof(CommonConfigurationBuilder).Module, true); + typeof(CommonSectionBuilder).Module, true); var il = method.GetILGenerator(); diff --git a/Apollo.ConfigurationManager/Key2XmlConfigurationBuilder.cs b/Apollo.ConfigurationManager/Key2XmlConfigurationBuilder.cs deleted file mode 100644 index d966d2c..0000000 --- a/Apollo.ConfigurationManager/Key2XmlConfigurationBuilder.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Xml; - -namespace Com.Ctrip.Framework.Apollo; - -public class Key2XmlConfigurationBuilder : ApolloConfigurationBuilder -{ - private string? _keyPrefix; - - public override void Initialize(string name, NameValueCollection config) - { - base.Initialize(name, config); - - _keyPrefix = config["keyPrefix"]; - } - - public override XmlNode ProcessRawXml(XmlNode rawXml) - { - rawXml.Bind(GetConfig(), string.IsNullOrEmpty(_keyPrefix) ? rawXml.Name : _keyPrefix!); - - return base.ProcessRawXml(rawXml); - } -} \ No newline at end of file diff --git a/Apollo.ConfigurationManager/README.md b/Apollo.ConfigurationManager/README.md index 3b6eda7..dcfe03d 100644 --- a/Apollo.ConfigurationManager/README.md +++ b/Apollo.ConfigurationManager/README.md @@ -1,9 +1,9 @@ -# 一、准备工作 +# 一、准备工作 > 如果想将传统的config配置(如web.config)转成json配置,可以使用[config2json](https://github.com/andrewlock/dotnet-config2json)工具 ## 1.1 环境要求 - + * NETFramework 4.5+ * NETFramework 4.7.1+(支持[ConfigurationBuilder](https://docs.microsoft.com/zh-cn/dotnet/api/system.configuration.configurationbuilder)) @@ -222,27 +222,13 @@ apollo.net项目中有多个样例客户端的项目: * 通过ConnectionStrings:ConnectionName:ConnectionString或者ConnectionStrings:ConnectionName来设置连接字符串(同时指定时ConnectionStrings:ConnectionName:ConnectionString优先级高) * 通过ConnectionStrings:ConnectionName:ProviderName来指定使用其他数据库,比如MySql.Data.MySqlClient来指定是MySql -## 4.3 CommonConfigurationBuilder +## 4.3 CommonSectionBuilder 通过反射结点类型,动态递归添加到节点类型中,此方法灵活,适应绝大部分节点。 ``` xml - - - - -``` -* namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 -* keyPrefix为可选值,默认是以节点名 - -## 4.4 Key2XmlConfigurationBuilder -通过简单的层次结构改换成xml,限制比较大,建议使用CommonConfigurationBuilder。 -``` xml - - - - + @@ -250,7 +236,7 @@ apollo.net项目中有多个样例客户端的项目: * namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 * keyPrefix为可选值,默认是以节点名 -## 4.5 NodeReplaceSectionBuilder +## 4.4 NodeReplaceSectionBuilder 直接使用apollo中配置的xml替换掉原来的节点xml ``` xml From 555424828bdbe193167cfe5c942ac197ba33b400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 19 Nov 2021 14:50:41 +0800 Subject: [PATCH 3/4] =?UTF-8?q?AppSettingsSectionBuilder=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=89=8D=E7=BC=80=E3=80=81CommonSectionBuild?= =?UTF-8?q?er=E3=80=81ConnectionStringsSectionBuilder=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E4=B8=8D=E4=BD=BF=E7=94=A8=E5=89=8D=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apollo.ConfigurationManager.Tests/App.config | 6 +- .../ConfigExtensionsTest.cs | 88 +++++++++++++++++++ .../ConfigurationBuilderTest.cs | 2 +- .../GetChildrenTest.cs | 35 -------- .../TestConfigurationSection.cs | 4 +- .../XmlExtensionsTest.cs | 41 --------- .../Apollo.ConfigurationManager.csproj | 1 - .../AppSettingsSectionBuilder.cs | 17 +++- .../CommonSectionBuilder.cs | 16 ++-- .../ConfigExtensions.cs | 81 +++++++++++++++-- .../ConnectionStringsSectionBuilder.cs | 22 ++--- .../NodeReplaceSectionBuilder.cs | 6 +- Apollo.ConfigurationManager/README.md | 13 +-- Apollo.ConfigurationManager/XmlExtensions.cs | 51 ----------- 14 files changed, 209 insertions(+), 174 deletions(-) create mode 100644 Apollo.ConfigurationManager.Tests/ConfigExtensionsTest.cs delete mode 100644 Apollo.ConfigurationManager.Tests/GetChildrenTest.cs delete mode 100644 Apollo.ConfigurationManager.Tests/XmlExtensionsTest.cs delete mode 100644 Apollo.ConfigurationManager/XmlExtensions.cs diff --git a/Apollo.ConfigurationManager.Tests/App.config b/Apollo.ConfigurationManager.Tests/App.config index 0018bd9..cbb5a98 100644 --- a/Apollo.ConfigurationManager.Tests/App.config +++ b/Apollo.ConfigurationManager.Tests/App.config @@ -11,7 +11,7 @@ - + @@ -28,7 +28,9 @@ - + + + diff --git a/Apollo.ConfigurationManager.Tests/ConfigExtensionsTest.cs b/Apollo.ConfigurationManager.Tests/ConfigExtensionsTest.cs new file mode 100644 index 0000000..639c5bb --- /dev/null +++ b/Apollo.ConfigurationManager.Tests/ConfigExtensionsTest.cs @@ -0,0 +1,88 @@ +using Com.Ctrip.Framework.Apollo; +using Xunit; + +namespace Apollo.ConfigurationManager.Tests; + +public class ConfigExtensionsTest +{ + [Fact] + public void GetChildren() + { + var config = new TestConfig(Create("a:B", "1"), Create("A:c", "2"), Create("A:C:d", "4"), Create("b", "3")); + + Assert.Equal(new[] { "a", "b" }, config.GetChildren("").Select(x => x.Name)); + Assert.Equal(new[] { "B", "c" }, config.GetChildren("a").Select(x => x.Name)); + Assert.Equal(new[] { "a:B", "A:c" }, config.GetChildren("a").Select(x => x.FullName)); + } + + [Fact] + public void GetConnectionStrings_ConnectionString_Prior() + { + var config = new TestConfig(Create("a:b", "123"), Create("a:b:ConnectionString", "abc")); + + var connectionString = config.GetConnectionStrings("a", "sql").Single(); + + Assert.Equal("b", connectionString.Name); + Assert.Equal("abc", connectionString.ConnectionString); + Assert.Equal("sql", connectionString.ProviderName); + } + + [Fact] + public void GetConnectionStrings_ProviderName() + { + var config = new TestConfig(Create("a:b", "123"), Create("a:b:ProviderName", "abc")); + + var connectionString = config.GetConnectionStrings("a", "sql").Single(); + + Assert.Equal("123", connectionString.ConnectionString); + Assert.Equal("abc", connectionString.ProviderName); + } + + [Fact] + public void GetConnectionStrings_No_Prefix() + { + var config = new TestConfig(Create("a", "123")); + + var connectionString = config.GetConnectionStrings("", "sql").Single(); + + Assert.Equal("a", connectionString.Name); + Assert.Equal("123", connectionString.ConnectionString); + } + + [Fact] + public void WithPrefix() + { + IConfig config = new TestConfig(Create("a:B", "1"), Create("A:c", "2"), Create("A:C:d", "4"), Create("b", "3")); + + Assert.Same(config, config.WithPrefix(" ")); + + config = config.WithPrefix("a"); + + Assert.Equal(new[] { "B", "c", "C:d" }, config.GetPropertyNames()); + Assert.Equal(new[] { "1", "2", "4" }, config.GetPropertyNames().Select(p => config.GetProperty(p, ""))); + } + + private static KeyValuePair Create(string key, string value) => new(key, value); + + private class TestConfig : IConfig + { + private readonly IReadOnlyDictionary _dict; + + public TestConfig(params KeyValuePair[] keyValues) + { + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var kv in keyValues) dict[kv.Key] = kv.Value; + + _dict = dict; + } + + public bool TryGetProperty(string key, [NotNullWhen(true)] out string? value) => + _dict.TryGetValue(key, out value); + + public IEnumerable GetPropertyNames() => _dict.Keys; + + public event ConfigChangeEvent ConfigChanged = default!; + } +} + diff --git a/Apollo.ConfigurationManager.Tests/ConfigurationBuilderTest.cs b/Apollo.ConfigurationManager.Tests/ConfigurationBuilderTest.cs index a4b3124..8014765 100644 --- a/Apollo.ConfigurationManager.Tests/ConfigurationBuilderTest.cs +++ b/Apollo.ConfigurationManager.Tests/ConfigurationBuilderTest.cs @@ -8,7 +8,7 @@ public class ConfigurationBuilderTest #if NET471_OR_GREATER [Fact] public void AppSettingsSectionBuilderTest() => - Assert.Equal("560", System.Configuration.ConfigurationManager.AppSettings["Timeout"]); + Assert.Equal("00:00:30", System.Configuration.ConfigurationManager.AppSettings["Timeout"]); [Fact] public void ConnectionStringsSectionBuilderTest() => diff --git a/Apollo.ConfigurationManager.Tests/GetChildrenTest.cs b/Apollo.ConfigurationManager.Tests/GetChildrenTest.cs deleted file mode 100644 index f42bb11..0000000 --- a/Apollo.ConfigurationManager.Tests/GetChildrenTest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Com.Ctrip.Framework.Apollo; -using Xunit; - -namespace Apollo.ConfigurationManager.Tests; - -public class GetChildrenTest -{ - [Fact] - public void Test() - { - var config = new FakeConfig(new Dictionary - { - { "a:B", "1" }, - { "A:c", "2" }, - { "A:C:d", "4" }, - }); - - Assert.Equal(new[] { "B", "c" }, config.GetChildren("a").Select(x => x.Name)); - Assert.Equal(new[] { "a:B", "A:c" }, config.GetChildren("a").Select(x => x.FullName)); - Assert.Equal(new[] { "d" }, config.GetChildren("a:C").Select(x => x.Name)); - } - - private class FakeConfig : IConfig - { - private readonly IReadOnlyDictionary _data; - - public event ConfigChangeEvent ConfigChanged = default!; - - public FakeConfig(IReadOnlyDictionary data) => _data = data; - - public IEnumerable GetPropertyNames() => _data.Keys; - - public bool TryGetProperty(string key, [NotNullWhen(true)] out string? value) => _data.TryGetValue(key, out value); - } -} \ No newline at end of file diff --git a/Apollo.ConfigurationManager.Tests/TestConfigurationSection.cs b/Apollo.ConfigurationManager.Tests/TestConfigurationSection.cs index c772686..2cf5238 100644 --- a/Apollo.ConfigurationManager.Tests/TestConfigurationSection.cs +++ b/Apollo.ConfigurationManager.Tests/TestConfigurationSection.cs @@ -16,6 +16,6 @@ public class TestConfigurationSection : ConfigurationSection [ConfigurationProperty("element")] public NameValueConfigurationElement Element => (NameValueConfigurationElement)this["element"]; - [ConfigurationProperty("", IsDefaultCollection = true)] - public KeyValueConfigurationCollection Map => (KeyValueConfigurationCollection)this[""]; + [ConfigurationProperty("map")] + public KeyValueConfigurationCollection Map => (KeyValueConfigurationCollection)this["map"]; } diff --git a/Apollo.ConfigurationManager.Tests/XmlExtensionsTest.cs b/Apollo.ConfigurationManager.Tests/XmlExtensionsTest.cs deleted file mode 100644 index 3686095..0000000 --- a/Apollo.ConfigurationManager.Tests/XmlExtensionsTest.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Com.Ctrip.Framework.Apollo; -using Com.Ctrip.Framework.Apollo.ConfigAdapter; -using Com.Ctrip.Framework.Apollo.Core.Utils; -using System.Xml; -using Xunit; - -namespace Apollo.ConfigurationManager.Tests; - -public class XmlExtensionsTest -{ -#if NET471_OR_GREATER - [Theory] - [InlineData("def", - "", - "def")] - public void BindTest(string originalXml, string newXml, string resultXml) - { - var doc = new XmlDocument(); - - doc.LoadXml(originalXml); - - XmlNode? node = doc.DocumentElement; - - node?.Bind(new FakeConfig(new XmlConfigAdapter().GetProperties($"{newXml}")), node.Name); - - Assert.Equal(resultXml, node?.OuterXml); - } -#endif - private class FakeConfig : IConfig - { - private readonly Properties _data; - - public event ConfigChangeEvent ConfigChanged = default!; - - public FakeConfig(Properties data) => _data = data; - - public IEnumerable GetPropertyNames() => _data.GetPropertyNames(); - - public bool TryGetProperty(string key, [NotNullWhen(true)] out string? value) => _data.TryGetProperty(key, out value); - } -} \ No newline at end of file diff --git a/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj b/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj index 39f901f..ef2bf44 100644 --- a/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj +++ b/Apollo.ConfigurationManager/Apollo.ConfigurationManager.csproj @@ -35,7 +35,6 @@ $(PackageReleaseNotes) - diff --git a/Apollo.ConfigurationManager/AppSettingsSectionBuilder.cs b/Apollo.ConfigurationManager/AppSettingsSectionBuilder.cs index 70493a9..272c5e6 100644 --- a/Apollo.ConfigurationManager/AppSettingsSectionBuilder.cs +++ b/Apollo.ConfigurationManager/AppSettingsSectionBuilder.cs @@ -5,6 +5,18 @@ namespace Com.Ctrip.Framework.Apollo; public class AppSettingsSectionBuilder : ApolloConfigurationBuilder { + private string? _keyPrefix; + + public override void Initialize(string name, NameValueCollection config) + { + base.Initialize(name, config); + + _keyPrefix = config["keyPrefix"]; + + if (!string.IsNullOrWhiteSpace(_keyPrefix) && !_keyPrefix.EndsWith(":")) + _keyPrefix += ":"; + } + public override ConfigurationSection ProcessConfigurationSection(ConfigurationSection configSection) { if (configSection is not AppSettingsSection section) return base.ProcessConfigurationSection(configSection); @@ -15,7 +27,8 @@ public override ConfigurationSection ProcessConfigurationSection(ConfigurationSe lock (this) { - var config = GetConfig(); + var config = GetConfig().WithPrefix(_keyPrefix); + foreach (var key in config.GetPropertyNames()) { if (config.TryGetProperty(key, out var value)) @@ -39,4 +52,4 @@ private static void TrySetConfigUtil(KeyValueConfigurationCollection appSettings ConfigUtil.AppSettings = settings; } -} \ No newline at end of file +} diff --git a/Apollo.ConfigurationManager/CommonSectionBuilder.cs b/Apollo.ConfigurationManager/CommonSectionBuilder.cs index 412a3cc..6a05131 100644 --- a/Apollo.ConfigurationManager/CommonSectionBuilder.cs +++ b/Apollo.ConfigurationManager/CommonSectionBuilder.cs @@ -49,13 +49,13 @@ public override void Initialize(string name, NameValueCollection config) { base.Initialize(name, config); - _keyPrefix = config["keyPrefix"]; + _keyPrefix = config["keyPrefix"]?.TrimEnd(':'); } public override ConfigurationSection ProcessConfigurationSection(ConfigurationSection configSection) { - Bind(configSection, GetConfig(), string.IsNullOrEmpty(_keyPrefix) - ? new ConfigKey(configSection.SectionInformation.SectionName, configSection.SectionInformation.SectionName) + Bind(configSection, GetConfig(), string.IsNullOrWhiteSpace(_keyPrefix ??= configSection.SectionInformation.SectionName) + ? new ConfigKey("", "") : new ConfigKey(_keyPrefix!.Substring(_keyPrefix!.LastIndexOf(':') + 1), _keyPrefix)); return configSection; @@ -63,12 +63,15 @@ public override ConfigurationSection ProcessConfigurationSection(ConfigurationSe private static void Bind(ConfigurationElement configElement, IConfig config, ConfigKey configKey) { + if (string.IsNullOrWhiteSpace(configKey.FullName) && + configElement is not ConfigurationSection) return; + foreach (var property in configElement.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { var cpa = property.GetCustomAttribute(); if (cpa == null) continue; - var key = $"{configKey.FullName}:{cpa.Name}"; + var key = string.IsNullOrWhiteSpace(configKey.FullName) ? cpa.Name : $"{configKey.FullName}:{cpa.Name}"; if (typeof(ConfigurationElement).IsAssignableFrom(property.PropertyType)) { @@ -94,7 +97,7 @@ private static void Bind(ConfigurationElement configElement, IConfig config, Con ExceptionDispatchInfo? ex = null; - if (cpa.IsKey) + if (cpa.IsKey && !string.IsNullOrWhiteSpace(configKey.Name)) try { SetValue(configElement, cp, configKey.Name); @@ -104,6 +107,7 @@ private static void Bind(ConfigurationElement configElement, IConfig config, Con ex = ExceptionDispatchInfo.Capture(e); } else if (string.Equals("value", cpa.Name, StringComparison.OrdinalIgnoreCase) && + !string.IsNullOrWhiteSpace(configKey.FullName) && config.TryGetProperty(configKey.FullName, out var value)) try { @@ -133,7 +137,7 @@ private static Action Crea MethodInfo GetMethod(string method, params Type[] parameterTypes) { - var ms = methods!.Where(m => m.Name == method).ToArray(); + var ms = methods.Where(m => m.Name == method).ToArray(); if (parameterTypes.Length < 1) return ms.FirstOrDefault(m => m.GetParameters().Length == 0) ?? ms.First(); return ms.First(m => diff --git a/Apollo.ConfigurationManager/ConfigExtensions.cs b/Apollo.ConfigurationManager/ConfigExtensions.cs index 99b5ce1..63a0847 100644 --- a/Apollo.ConfigurationManager/ConfigExtensions.cs +++ b/Apollo.ConfigurationManager/ConfigExtensions.cs @@ -1,25 +1,63 @@ -namespace Com.Ctrip.Framework.Apollo; +using System.Configuration; + +namespace Com.Ctrip.Framework.Apollo; internal static class ConfigExtensions { public static IEnumerable GetChildren(this IConfig config, string keyPrefix) { - keyPrefix += ":"; - var hash = new HashSet(StringComparer.OrdinalIgnoreCase); - foreach (var propertyName in config.GetPropertyNames()) + if (string.IsNullOrWhiteSpace(keyPrefix)) { - if (!propertyName.StartsWith(keyPrefix, StringComparison.OrdinalIgnoreCase)) continue; + foreach (var propertyName in config.GetPropertyNames()) + { + var index = propertyName.IndexOf(':'); - var index = propertyName.IndexOf(':', keyPrefix.Length); + hash.Add(index > 0 ? propertyName.Substring(0, index) : propertyName); + } + } + else + { + keyPrefix += ":"; - hash.Add(index > 0 ? propertyName.Substring(0, index) : propertyName); + foreach (var propertyName in config.GetPropertyNames()) + { + if (!propertyName.StartsWith(keyPrefix, StringComparison.OrdinalIgnoreCase)) continue; + + var index = propertyName.IndexOf(':', keyPrefix.Length); + + hash.Add(index > 0 ? propertyName.Substring(0, index) : propertyName); + } } return hash.Select(key => new ConfigKey(key.Substring(key.LastIndexOf(':') + 1), key)); } + public static IEnumerable GetConnectionStrings(this IConfig config, + string keyPrefix, string? defaultProviderName) + { + string keyPrefixAndColon; + if (string.IsNullOrWhiteSpace(keyPrefix)) keyPrefixAndColon = keyPrefix = ""; + else keyPrefixAndColon = keyPrefix + ":"; + + foreach (var name in config.GetChildren(keyPrefix)) + { + var connectionName = name.Name; + + if (!config.TryGetProperty($"{keyPrefixAndColon}{connectionName}:ConnectionString", out var connectionString) && + !config.TryGetProperty($"{keyPrefixAndColon}{connectionName}", out connectionString) || + string.IsNullOrWhiteSpace(connectionString)) continue; + + config.TryGetProperty($"{keyPrefixAndColon}{connectionName}:ProviderName", out var providerName); + + yield return new ConnectionStringSettings(connectionName, connectionString, providerName ?? defaultProviderName); + } + } + + public static IConfig WithPrefix(this IConfig config, string? keyPrefix) => + string.IsNullOrWhiteSpace(keyPrefix) ? config : new KeyPrefixConfig(config, keyPrefix!); + public struct ConfigKey { public ConfigKey(string name, string fullName) @@ -33,4 +71,31 @@ public ConfigKey(string name, string fullName) public string FullName { get; } } -} \ No newline at end of file + + private class KeyPrefixConfig : IConfig + { + private readonly IConfig _config; + private readonly string _keyPrefix; + + public KeyPrefixConfig(IConfig config, string keyPrefix) + { + _config = config; + + _keyPrefix = keyPrefix + ":"; + } + + public bool TryGetProperty(string key, [NotNullWhen(true)] out string? value) => + _config.TryGetProperty(_keyPrefix + key, out value); + + public IEnumerable GetPropertyNames() => _config.GetPropertyNames() + .Where(propertyName => propertyName.Length > _keyPrefix.Length && + propertyName.StartsWith(_keyPrefix, StringComparison.OrdinalIgnoreCase)) + .Select(propertyName => propertyName.Substring(_keyPrefix.Length)); + + public event ConfigChangeEvent? ConfigChanged + { + add => _config.ConfigChanged += value; + remove => _config.ConfigChanged -= value; + } + } +} diff --git a/Apollo.ConfigurationManager/ConnectionStringsSectionBuilder.cs b/Apollo.ConfigurationManager/ConnectionStringsSectionBuilder.cs index 249c7ac..d9dcfa1 100644 --- a/Apollo.ConfigurationManager/ConnectionStringsSectionBuilder.cs +++ b/Apollo.ConfigurationManager/ConnectionStringsSectionBuilder.cs @@ -12,7 +12,7 @@ public override void Initialize(string name, NameValueCollection config) { base.Initialize(name, config); - _keyPrefix = config["keyPrefix"]; + _keyPrefix = config["keyPrefix"]?.TrimEnd(':'); _defaultProviderName = config["defaultProviderName"] ?? "System.Data.SqlClient"; } @@ -25,26 +25,14 @@ public override ConfigurationSection ProcessConfigurationSection(ConfigurationSe lock (this) { - var config = GetConfig(); - - if (string.IsNullOrEmpty(_keyPrefix)) _keyPrefix = configSection.SectionInformation.Name; - - foreach (var name in config.GetChildren(_keyPrefix!)) + foreach (var connectionString in GetConfig().GetConnectionStrings(_keyPrefix ?? configSection.SectionInformation.Name, _defaultProviderName)) { - var connectionName = name.Name; - - if (!config.TryGetProperty($"{_keyPrefix}:{connectionName}:ConnectionString", out var connectionString) && - !config.TryGetProperty($"{_keyPrefix}:{connectionName}", out connectionString) || - string.IsNullOrWhiteSpace(connectionString)) continue; - - connectionStrings.Remove(connectionName); - - config.TryGetProperty($"{_keyPrefix}:{connectionName}:ProviderName", out var providerName); + connectionStrings.Remove(connectionString.Name); - connectionStrings.Add(new ConnectionStringSettings(connectionName, connectionString, providerName ?? _defaultProviderName)); + connectionStrings.Add(connectionString); } } return base.ProcessConfigurationSection(configSection); } -} \ No newline at end of file +} diff --git a/Apollo.ConfigurationManager/NodeReplaceSectionBuilder.cs b/Apollo.ConfigurationManager/NodeReplaceSectionBuilder.cs index 3feac92..3ae699f 100644 --- a/Apollo.ConfigurationManager/NodeReplaceSectionBuilder.cs +++ b/Apollo.ConfigurationManager/NodeReplaceSectionBuilder.cs @@ -16,10 +16,10 @@ public override void Initialize(string name, NameValueCollection config) public override XmlNode ProcessRawXml(XmlNode rawXml) { - if (string.IsNullOrEmpty(_key)) _key = rawXml.Name; + if (string.IsNullOrWhiteSpace(_key)) _key = rawXml.Name; if (!GetConfig().TryGetProperty(_key!, out var xml) || - string.IsNullOrEmpty(xml)) + string.IsNullOrWhiteSpace(xml)) return base.ProcessRawXml(rawXml); var doc = new XmlDocument(); @@ -35,4 +35,4 @@ public override XmlNode ProcessRawXml(XmlNode rawXml) return base.ProcessRawXml(doc.DocumentElement!); } -} \ No newline at end of file +} diff --git a/Apollo.ConfigurationManager/README.md b/Apollo.ConfigurationManager/README.md index dcfe03d..795da21 100644 --- a/Apollo.ConfigurationManager/README.md +++ b/Apollo.ConfigurationManager/README.md @@ -199,12 +199,13 @@ apollo.net项目中有多个样例客户端的项目: - + ``` * namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 +* keyPrefix为可选值,当值不是IsNullOrWhiteSpace时生效 ## 4.2 ConnectionStringsSectionBuilder ``` xml @@ -218,12 +219,14 @@ apollo.net项目中有多个样例客户端的项目: ``` * namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 * defaultProviderName为可选值,默认值为System.Data.SqlClient,,对应ConnectionString的ProviderName。 -* keyPrefix为可选值,默认值是connectionStrings +* keyPrefix为可选值,没有配置时值为节点名(一般是connectionStrings),值是WhiteSpace时则不生效 * 通过ConnectionStrings:ConnectionName:ConnectionString或者ConnectionStrings:ConnectionName来设置连接字符串(同时指定时ConnectionStrings:ConnectionName:ConnectionString优先级高) * 通过ConnectionStrings:ConnectionName:ProviderName来指定使用其他数据库,比如MySql.Data.MySqlClient来指定是MySql ## 4.3 CommonSectionBuilder -通过反射结点类型,动态递归添加到节点类型中,此方法灵活,适应绝大部分节点。 + +通过反射结点类型,动态递归添加到节点类型中,此方法灵活,适应绝大部分节点。通过读取属性的[ConfigurationProperty]值和配置中的值关联 + ``` xml @@ -234,7 +237,7 @@ apollo.net项目中有多个样例客户端的项目: ``` * namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 -* keyPrefix为可选值,默认是以节点名 +* keyPrefix为可选值,没有配置时值为节点名,值是WhiteSpace时则不生效 ## 4.4 NodeReplaceSectionBuilder 直接使用apollo中配置的xml替换掉原来的节点xml @@ -248,7 +251,7 @@ apollo.net项目中有多个样例客户端的项目: ``` * namespace为可选值,该值对应apollo中的namespace。支持多个值,以`,`或`;`分割,优先级从低到高 -* key为可选值,默认是以节点名 +* key为可选值,当为IsNullOrWhiteSpace时值为节点名 # 五、FAQ diff --git a/Apollo.ConfigurationManager/XmlExtensions.cs b/Apollo.ConfigurationManager/XmlExtensions.cs deleted file mode 100644 index 5b060d5..0000000 --- a/Apollo.ConfigurationManager/XmlExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Xml; - -namespace Com.Ctrip.Framework.Apollo; - -internal static class XmlExtensions -{ - public static void Bind(this XmlNode? xmlNode, IConfig config, string keyPrefix) - { - if (xmlNode == null) return; - - foreach (var key in config.GetChildren(keyPrefix)) - { - if (config.GetChildren(key.FullName).Any()) - CreateXmlNode(xmlNode, key.Name).Bind(config, key.FullName); - else - AddOrUpdateAttribute(xmlNode, key.Name, config.GetProperty(key.FullName, "")); - } - } - - private static void AddOrUpdateAttribute(XmlNode xmlNode, string name, string value) - { - if (xmlNode.Attributes == null) return; - - foreach (XmlAttribute attr in xmlNode.Attributes) - { - if (attr.Name != name) continue; - - attr.Value = value; - - return; - } - - if (xmlNode.OwnerDocument == null) return; - - var createAttribute = xmlNode.OwnerDocument.CreateAttribute(name, xmlNode.NamespaceURI); - - createAttribute.Value = value; - - xmlNode.Attributes.Append(createAttribute); - } - - private static XmlNode? CreateXmlNode(XmlNode? xmlNode, string nodeName) - { - if (xmlNode?.OwnerDocument == null || string.IsNullOrEmpty(nodeName)) return null; - - if (xmlNode[nodeName] == null) - xmlNode.AppendChild(xmlNode.OwnerDocument.CreateElement(nodeName)); - - return xmlNode[nodeName]; - } -} \ No newline at end of file From 9838e3823e82926fe130b072a29869aec183ea80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 19 Nov 2021 14:53:28 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apollo.AspNetCoreHosting/Apollo.AspNetCoreHosting.csproj | 2 +- Apollo.ConfigAdapter.Yaml/Apollo.ConfigAdapter.Yaml.csproj | 2 +- Apollo.Configuration/Apollo.Configuration.csproj | 2 +- Apollo.ExtensionsHosting/Apollo.ExtensionsHosting.csproj | 2 +- Apollo/Apollo.csproj | 2 +- Directory.Build.props | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Apollo.AspNetCoreHosting/Apollo.AspNetCoreHosting.csproj b/Apollo.AspNetCoreHosting/Apollo.AspNetCoreHosting.csproj index 0d2e389..e0a8303 100644 --- a/Apollo.AspNetCoreHosting/Apollo.AspNetCoreHosting.csproj +++ b/Apollo.AspNetCoreHosting/Apollo.AspNetCoreHosting.csproj @@ -15,7 +15,7 @@ $(PackageReleaseNotes) $(RepositoryUrl)/$(MSBuildProjectName) Microsoft.AspNetCore.Hosting netstandard2.0 - $(ApolloVersion) + $(ApolloVersion).0 diff --git a/Apollo.ConfigAdapter.Yaml/Apollo.ConfigAdapter.Yaml.csproj b/Apollo.ConfigAdapter.Yaml/Apollo.ConfigAdapter.Yaml.csproj index 656031e..d480fde 100644 --- a/Apollo.ConfigAdapter.Yaml/Apollo.ConfigAdapter.Yaml.csproj +++ b/Apollo.ConfigAdapter.Yaml/Apollo.ConfigAdapter.Yaml.csproj @@ -11,7 +11,7 @@ $(PackageReleaseNotes) $(PackageTags) yml yaml Com.Ctrip.Framework.Apollo.ConfigAdapter net40;net45;netstandard2.0 - $(ApolloVersion) + $(ApolloVersion).0 diff --git a/Apollo.Configuration/Apollo.Configuration.csproj b/Apollo.Configuration/Apollo.Configuration.csproj index 197abc7..f84fdbe 100644 --- a/Apollo.Configuration/Apollo.Configuration.csproj +++ b/Apollo.Configuration/Apollo.Configuration.csproj @@ -32,7 +32,7 @@ $(PackageReleaseNotes) $(RepositoryUrl)/$(MSBuildProjectName) Com.Ctrip.Framework.Apollo netstandard2.0 - $(ApolloVersion) + $(ApolloVersion).0 diff --git a/Apollo.ExtensionsHosting/Apollo.ExtensionsHosting.csproj b/Apollo.ExtensionsHosting/Apollo.ExtensionsHosting.csproj index ee464c8..185912c 100644 --- a/Apollo.ExtensionsHosting/Apollo.ExtensionsHosting.csproj +++ b/Apollo.ExtensionsHosting/Apollo.ExtensionsHosting.csproj @@ -14,7 +14,7 @@ $(PackageReleaseNotes) $(RepositoryUrl)/$(MSBuildProjectName) Microsoft.Extensions.Hosting netstandard2.0 - $(ApolloVersion) + $(ApolloVersion).0 diff --git a/Apollo/Apollo.csproj b/Apollo/Apollo.csproj index c9ec631..8a1e6ee 100644 --- a/Apollo/Apollo.csproj +++ b/Apollo/Apollo.csproj @@ -14,7 +14,7 @@ $(PackageReleaseNotes) $(RepositoryUrl)/$(MSBuildProjectName) Com.Ctrip.Framework.Apollo net40;net45;netstandard2.0;netstandard2.1 - $(ApolloVersion) + $(ApolloVersion).0 diff --git a/Directory.Build.props b/Directory.Build.props index 4f1a5c9..b66811d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@  - 2.5.0 + 2.5 ..\Apollo.snk 2.0.0 True