diff --git a/OptionStudy.Next/2配置模型/IConfigurationProviderTest.cs b/OptionStudy.Next/2配置模型/IConfigurationProviderTest.cs
index c0268cb..aff4db7 100644
--- a/OptionStudy.Next/2配置模型/IConfigurationProviderTest.cs
+++ b/OptionStudy.Next/2配置模型/IConfigurationProviderTest.cs
@@ -58,7 +58,7 @@ namespace OptionStudy.Next
Action run = () =>
{
provider.Set("TestName", "UpdateName");
- if (!provider.TryGet("Demo", out string _v))
+ if (!provider.TryGet("Demo", out var _v))
{
provider.Add("Demo", "demo");
}
@@ -88,7 +88,7 @@ namespace OptionStudy.Next
};
- var provider = source.Build(null);
+ var provider = source.Build(new ConfigurationBuilder());
var hasName = provider.TryGet("AppName", out _);
Assert.NotNull(provider);
diff --git a/OptionStudy.Next/2配置模型/Point.cs b/OptionStudy.Next/2配置模型/Point.cs
new file mode 100644
index 0000000..058b59f
--- /dev/null
+++ b/OptionStudy.Next/2配置模型/Point.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OptionStudy.Next
+{
+ [TypeConverter(typeof(PointTypeConverter))]
+ public readonly record struct Point(double x, double y);
+}
diff --git a/OptionStudy.Next/2配置模型/PointTypeConverter.cs b/OptionStudy.Next/2配置模型/PointTypeConverter.cs
new file mode 100644
index 0000000..4746615
--- /dev/null
+++ b/OptionStudy.Next/2配置模型/PointTypeConverter.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OptionStudy.Next
+{
+ public class PointTypeConverter: TypeConverter
+ {
+ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
+ {
+ return sourceType == typeof(string);
+ }
+
+ public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
+ {
+ var split = (value.ToString()??"0.0,0.0").Split(',');
+ double x = double.Parse(split[0].Trim().TrimStart('('));
+ double y = double.Parse(split[1].Trim().TrimEnd(')'));
+
+ return new Point(x, y);
+ }
+ }
+}
diff --git a/OptionStudy.Next/3配置绑定/ConfigBinderTest.cs b/OptionStudy.Next/3配置绑定/ConfigBinderTest.cs
new file mode 100644
index 0000000..f63d759
--- /dev/null
+++ b/OptionStudy.Next/3配置绑定/ConfigBinderTest.cs
@@ -0,0 +1,265 @@
+
+using OptionStudy.UnitApp.Next;
+
+namespace OptionStudy.Next._3配置绑定
+{
+ ///
+ /// 配置绑定 测试
+ /// 引用 Microsoft.Extensions.Configuration.Binder 包
+ ///
+ public class ConfigBinderTest : IDisposable
+ {
+ private readonly ITestOutputHelper testOutput;
+
+ public ConfigBinderTest(ITestOutputHelper testOutputHelper)
+ {
+ this.testOutput = testOutputHelper;
+ }
+
+ ///
+ /// 绑定配置项的值
+ ///
+ [Fact]
+ public void Binder_ConfigItem_Test()
+ {
+ IDictionary memoryData = new Dictionary()
+ {
+ ["AppName"] = "MemoryAppName",
+ ["AppVersion"] = "0.0.0.1",
+ ["EMail:ReceiveAddress"] = "memory@163.com",
+ ["EMail:Recipient"] = "memory",
+ ["foo"] = null,
+ ["bar"] = "",
+ ["baz"] = "123",
+ };
+
+ var root = new ConfigurationBuilder().AddInMemoryCollection(memoryData).Build();
+
+ //针对 object : 直接返回原始值(字符串或null)
+ Assert.Null(root.GetValue