U:调整Config模块功能调整Server模块集成效果
This commit is contained in:
1 parent
b14721d79e
commit
53d1dd2dbf
17 files changed
+122
-86
No files matched your search
@@ -5,6 +5,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Common;
|
using Common;
|
||||||
using Config;
|
using Config;
|
||||||
using NetClient.DependencyInjection;
|
using NetClient.DependencyInjection;
|
||||||
|
using Sharp.Infrastructure.Configuration;
|
||||||
using Sharp.Log.Extensions;
|
using Sharp.Log.Extensions;
|
||||||
using Sharp.NetServer.DependencyInjection;
|
using Sharp.NetServer.DependencyInjection;
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<ProjectReference Include="..\NetClient\NetClient.csproj" />
|
<ProjectReference Include="..\NetClient\NetClient.csproj" />
|
||||||
<ProjectReference Include="..\NetServer\NetServer.csproj" />
|
<ProjectReference Include="..\NetServer\NetServer.csproj" />
|
||||||
<ProjectReference Include="..\Log\Log.csproj" />
|
<ProjectReference Include="..\Log\Log.csproj" />
|
||||||
|
<ProjectReference Include="..\Sharp.Infrastructure\Sharp.Infrastructure.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -6,14 +6,16 @@ namespace Config;
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 描述默认配置构建时的约定。
|
/// 描述默认配置构建时的约定。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ConfigDefaultsOptions
|
public sealed class ConfigDefaultsOptions
|
||||||
{
|
|
||||||
public ConfigDefaultsOptions()
|
|
||||||
{
|
{
|
||||||
BasePath = AppContext.BaseDirectory;
|
private readonly IList<ConfigSource> _fluentSources = new List<ConfigSource>();
|
||||||
EnvironmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")
|
|
||||||
?? Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
|
public ConfigDefaultsOptions()
|
||||||
|
{
|
||||||
|
BasePath = AppContext.BaseDirectory;
|
||||||
|
EnvironmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")
|
||||||
|
?? Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -60,6 +62,43 @@ public sealed class ConfigDefaultsOptions
|
|||||||
/// 额外的配置源描述,便于手动指定 Optional 或自定义格式。
|
/// 额外的配置源描述,便于手动指定 Optional 或自定义格式。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<ConfigSource> AdditionalSources { get; } = new List<ConfigSource>();
|
public IList<ConfigSource> AdditionalSources { get; } = new List<ConfigSource>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过流式 API 添加 JSON 配置文件(默认 optional)。
|
||||||
|
/// </summary>
|
||||||
|
public ConfigDefaultsOptions WithJson(string path, bool optional = true) =>
|
||||||
|
AddFluentSource(path, ConfigFormat.Json, optional);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过流式 API 添加 INI 配置文件(默认 optional)。
|
||||||
|
/// </summary>
|
||||||
|
public ConfigDefaultsOptions WithIni(string path, bool optional = true) =>
|
||||||
|
AddFluentSource(path, ConfigFormat.Ini, optional);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过流式 API 添加 XML 配置文件(默认 optional)。
|
||||||
|
/// </summary>
|
||||||
|
public ConfigDefaultsOptions WithXml(string path, bool optional = true) =>
|
||||||
|
AddFluentSource(path, ConfigFormat.Xml, optional);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过流式 API 添加 TOML 配置文件(默认 optional)。
|
||||||
|
/// </summary>
|
||||||
|
public ConfigDefaultsOptions WithToml(string path, bool optional = true) =>
|
||||||
|
AddFluentSource(path, ConfigFormat.Toml, optional);
|
||||||
|
|
||||||
|
private ConfigDefaultsOptions AddFluentSource(string path, ConfigFormat format, bool optional)
|
||||||
|
{
|
||||||
|
_fluentSources.Add(new ConfigSource
|
||||||
|
{
|
||||||
|
Path = path,
|
||||||
|
Format = format,
|
||||||
|
Optional = optional
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IEnumerable<ConfigSource> GetFluentSources() => _fluentSources;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -97,6 +136,14 @@ public static class ConfigDefaults
|
|||||||
return manager.Get<T>(section, validate);
|
return manager.Get<T>(section, validate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T Load<T>(Action<ConfigDefaultsOptions> defaults,
|
||||||
|
bool validate = true,
|
||||||
|
string? section = null,
|
||||||
|
Action<ConfigOptions>? configure = null) where T : new()
|
||||||
|
{
|
||||||
|
return Load<T>(validate, section, defaults, configure);
|
||||||
|
}
|
||||||
|
|
||||||
internal static void ApplyDefaults(ConfigOptions target, ConfigDefaultsOptions defaults)
|
internal static void ApplyDefaults(ConfigOptions target, ConfigDefaultsOptions defaults)
|
||||||
{
|
{
|
||||||
if (defaults.BasePath is not null)
|
if (defaults.BasePath is not null)
|
||||||
@@ -120,6 +167,11 @@ public static class ConfigDefaults
|
|||||||
target.Sources.Add(CreateSource(file, optional: true));
|
target.Sources.Add(CreateSource(file, optional: true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var source in defaults.GetFluentSources())
|
||||||
|
{
|
||||||
|
target.Sources.Add(source);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var source in defaults.AdditionalSources)
|
foreach (var source in defaults.AdditionalSources)
|
||||||
{
|
{
|
||||||
target.Sources.Add(source);
|
target.Sources.Add(source);
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
||||||
|
|
||||||
namespace Config;
|
|
||||||
|
|
||||||
public interface ISystemConfigAccessor
|
|
||||||
{
|
|
||||||
SystemConfig Value { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal sealed class SystemConfigAccessor : ISystemConfigAccessor, IDisposable
|
|
||||||
{
|
|
||||||
private readonly ConfigManager _cm;
|
|
||||||
private readonly IDisposable _subscription;
|
|
||||||
private SystemConfig _current;
|
|
||||||
|
|
||||||
public SystemConfigAccessor(ConfigManager cm)
|
|
||||||
{
|
|
||||||
_cm = cm;
|
|
||||||
_current = cm.Get<SystemConfig>(section: "System", validate: false);
|
|
||||||
_subscription = cm.OnReload(() =>
|
|
||||||
{
|
|
||||||
// Reload on change
|
|
||||||
_current = _cm.Get<SystemConfig>(section: "System", validate: false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public SystemConfig Value => _current;
|
|
||||||
|
|
||||||
public void Dispose() => _subscription.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SystemConfigExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Registers SystemConfig accessor backed by ConfigManager under the "System" section.
|
|
||||||
/// </summary>
|
|
||||||
public static IServiceCollection AddSystemConfig(this IServiceCollection services, ConfigManager cm)
|
|
||||||
{
|
|
||||||
services.TryAddSingleton(cm);
|
|
||||||
services.TryAddSingleton<ISystemConfigAccessor, SystemConfigAccessor>();
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -46,7 +46,8 @@ var settings = ConfigDefaults.Load<AppSettings>();
|
|||||||
var manager = ConfigDefaults.BuildDefault(opt =>
|
var manager = ConfigDefaults.BuildDefault(opt =>
|
||||||
{
|
{
|
||||||
opt.EnvironmentPrefix = "APP"; // 仅读取 APP__ 前缀的环境变量
|
opt.EnvironmentPrefix = "APP"; // 仅读取 APP__ 前缀的环境变量
|
||||||
opt.AdditionalFiles.Add("extra.ini"); // 按需附加其它文件,默认 optional
|
opt.WithIni("extra.ini") // 同时加载 INI
|
||||||
|
.WithToml("feature.toml"); // 以及 TOML
|
||||||
});
|
});
|
||||||
var settings = manager.Get<AppSettings>(validate: true);
|
var settings = manager.Get<AppSettings>(validate: true);
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Config;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Global system-level configuration, shared across modules.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SystemConfig
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
[RegularExpression(@"^([0-9]{1,3}\.){3}[0-9]{1,3}$|^localhost$|^[a-zA-Z0-9_.-]+$")]
|
|
||||||
public string HTTPIp { get; set; } = "127.0.0.1";
|
|
||||||
|
|
||||||
[Range(1, 65535)]
|
|
||||||
public int HttpPort { get; set; } = 8080;
|
|
||||||
|
|
||||||
[Range(1, 600)]
|
|
||||||
public int TimeoutSeconds { get; set; } = 30;
|
|
||||||
|
|
||||||
public string Scheme { get; set; } = "http";
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -11,7 +11,8 @@ var settings = ConfigDefaults.Load<AppSettings>();
|
|||||||
// 如果需要继续访问 IConfiguration,可先拿到 ConfigManager
|
// 如果需要继续访问 IConfiguration,可先拿到 ConfigManager
|
||||||
var cm = ConfigDefaults.BuildDefault(defaults =>
|
var cm = ConfigDefaults.BuildDefault(defaults =>
|
||||||
{
|
{
|
||||||
defaults.AdditionalFiles.Add("extra.ini");
|
defaults.WithIni("extra.ini")
|
||||||
|
.WithToml("feature.toml");
|
||||||
defaults.EnvironmentPrefix = "APP";
|
defaults.EnvironmentPrefix = "APP";
|
||||||
});
|
});
|
||||||
var settings2 = cm.Get<AppSettings>(validate: true);
|
var settings2 = cm.Get<AppSettings>(validate: true);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Config;
|
using Config;
|
||||||
using NetClient.Options;
|
using NetClient.Options;
|
||||||
|
using Sharp.Infrastructure.Configuration;
|
||||||
|
|
||||||
namespace NetClient.DependencyInjection;
|
namespace NetClient.DependencyInjection;
|
||||||
|
|
||||||
@@ -44,4 +45,3 @@ public static class ConfigurationExtensions
|
|||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Common\Common.csproj" />
|
<ProjectReference Include="..\Common\Common.csproj" />
|
||||||
<ProjectReference Include="..\Config\Config.csproj" />
|
<ProjectReference Include="..\Config\Config.csproj" />
|
||||||
|
<ProjectReference Include="..\Sharp.Infrastructure\Sharp.Infrastructure.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Config;
|
using Config;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
using Sharp.Infrastructure.Configuration;
|
||||||
using Sharp.NetServer.Server;
|
using Sharp.NetServer.Server;
|
||||||
|
|
||||||
namespace Sharp.NetServer.DependencyInjection;
|
namespace Sharp.NetServer.DependencyInjection;
|
||||||
@@ -26,4 +27,3 @@ public static class ServiceCollectionExtensions
|
|||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Common\Common.csproj" />
|
<ProjectReference Include="..\Common\Common.csproj" />
|
||||||
<ProjectReference Include="..\Config\Config.csproj" />
|
<ProjectReference Include="..\Config\Config.csproj" />
|
||||||
|
<ProjectReference Include="..\Sharp.Infrastructure\Sharp.Infrastructure.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -6,4 +6,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Config\Config.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// 此代码由工具生成。
|
// This code was generated by a tool.
|
||||||
// 运行时版本:4.0.30319.42000
|
|
||||||
//
|
//
|
||||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// 重新生成代码,这些更改将会丢失。
|
// the code is regenerated.
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Sharp.Wpf")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Sharp.Wpf")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+989747a2ae8392dd304ec136a20c73d2714a43b9")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b14721d79ee49603fd8600872fa22c984017bb5b")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Sharp.Wpf")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Sharp.Wpf")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Sharp.Wpf")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Sharp.Wpf")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
6c5c7e08ff66373e9981bab4e0ba90b429207193706551d9719bf8bb6534127e
|
9709e2b151cbd6395e6164fc9a4c93fdc4813fdcdf520d95d8fe511f945f3f99
|
||||||
@@ -1 +1 @@
|
|||||||
17633435623876895
|
17633497485167484
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
|
||||||
<PackageReference Include="MSTest" Version="3.6.4"/>
|
<PackageReference Include="MSTest" Version="3.6.4"/>
|
||||||
|
<PackageReference Include="MSTest.TestFramework" Version="3.6.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -115,6 +115,44 @@ namespace Config.Test
|
|||||||
Assert.AreEqual("fromToml", settings.RequiredField);
|
Assert.AreEqual("fromToml", settings.RequiredField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ConfigDefaults_Fluent_WithToml_AndOtherFormats_Works()
|
||||||
|
{
|
||||||
|
using var scope = new TempDirScope();
|
||||||
|
|
||||||
|
File.WriteAllText(scope.PathOf("appsettings.json"),
|
||||||
|
"{ \"Name\": \"default\", \"Port\": 20 }",
|
||||||
|
new UTF8Encoding(false));
|
||||||
|
|
||||||
|
File.WriteAllText(scope.PathOf("settings.ini"),
|
||||||
|
"[Database]\nHost=iniHost\nUser=iniUser\n",
|
||||||
|
new UTF8Encoding(false));
|
||||||
|
|
||||||
|
File.WriteAllText(scope.PathOf("extra.xml"),
|
||||||
|
"<settings><ValidPort>8080</ValidPort></settings>",
|
||||||
|
new UTF8Encoding(false));
|
||||||
|
|
||||||
|
File.WriteAllText(scope.PathOf("feature.toml"),
|
||||||
|
"RequiredField = \"fromToml\"\n",
|
||||||
|
new UTF8Encoding(false));
|
||||||
|
|
||||||
|
var settings = ConfigDefaults.Load<AppSettings>(defaults =>
|
||||||
|
{
|
||||||
|
defaults.BasePath = scope.Dir;
|
||||||
|
defaults.IncludeEnvironmentVariables = false;
|
||||||
|
defaults.WithIni("settings.ini")
|
||||||
|
.WithXml("extra.xml")
|
||||||
|
.WithToml("feature.toml");
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.AreEqual("default", settings.Name);
|
||||||
|
Assert.AreEqual(20, settings.Port);
|
||||||
|
Assert.AreEqual(8080, settings.ValidPort);
|
||||||
|
Assert.AreEqual("iniHost", settings.Database.Host);
|
||||||
|
Assert.AreEqual("iniUser", settings.Database.User);
|
||||||
|
Assert.AreEqual("fromToml", settings.RequiredField);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Validation_Fails_On_Missing_Required()
|
public void Validation_Fails_On_Missing_Required()
|
||||||
{
|
{
|
||||||
@@ -245,7 +283,10 @@ namespace Config.Test
|
|||||||
_ = cm.LoadFromFile<AppSettings>(toml, ConfigFormat.Toml);
|
_ = cm.LoadFromFile<AppSettings>(toml, ConfigFormat.Toml);
|
||||||
});
|
});
|
||||||
|
|
||||||
var cmToml = ConfigBuilder.BuildFromFiles(new[] { "a.toml" }, basePath: scope.Dir);
|
var cmToml = ConfigBuilder.BuildFromFiles(
|
||||||
|
new[] { "a.toml" },
|
||||||
|
basePath: scope.Dir,
|
||||||
|
includeEnvironment: false);
|
||||||
var tomlBack = cmToml.Get<AppSettings>();
|
var tomlBack = cmToml.Get<AppSettings>();
|
||||||
Assert.AreEqual("save", tomlBack.Name);
|
Assert.AreEqual("save", tomlBack.Name);
|
||||||
Assert.AreEqual("db", tomlBack.Database.Host);
|
Assert.AreEqual("db", tomlBack.Database.Host);
|
||||||
|
|||||||
Reference in new issue
Block a user