MC9*_*000 3 c# appsettings winforms .net-6.0
如何强制 Dotnet6 桌面 Winforms 应用程序使用 appsettings.json 而不是 Settings.settings[App.config]?
如果我在 Visual Studio 2022 中创建一个新的桌面应用程序以使用 Dotnet6.0,默认情况下,它会动态创建一个 Settings.settings 文件,然后也会创建一个 App.config 文件(这很奇怪,因为据说该文件已被弃用)在 Dotnet5.0 及更高版本中!)。
不幸的是,所有设置在安装/发布后都嵌入到应用程序中,并且一旦安装,就无法在应用程序文件夹中的任何位置进行更改。
对于较旧的 DotNet4.72 桌面应用程序,app.config 始终位于发布输出中,如果发生更改,应用程序将在执行时很好地读取任何更改。
我想像 Web 应用程序 (dotnet6.0) 一样使用 appsettings.json,并且有很多关于如何使用控制台应用程序 (dotnet6.0) 执行此操作的信息,但不适用于桌面窗口。
我有很多想要转换的 DotNet4.72 桌面应用程序,但它们仍然需要能够通过动态编辑文件(如果条件发生变化)来简单地更改配置设置。虽然我可以推出自己的解决方案,但我希望像在我的 Web 应用程序 (appsettings.json) 中那样执行此操作。更好的是,我希望看到一个 VS2022 桌面模板,每次为 DotNet6 和 7 创建新的桌面应用程序时都会执行此操作。
有任何想法吗?
Gab*_*bor 11
基本上你可以使用,Microsoft.Extensions.Configuration但你也可以使用Microsoft.Extensions.Hostingnuget 包。
这是一个经过测试的工作示例,也可以处理配置更改。
脚步:
appsettings.json到项目中。
Build ActionNoneCopy to Output DirectoryCopy alwaysSampleOptions:)appsettings.json。Microsoft.Extensions.Hosting将nuget 包添加到您的项目中。Program.cs:
IHostApplicationLifetime。IServiceScope使用主机的IServiceProvider.MainForm.Application.Run()使用已解析的实例调用方法MainForm。MainForm.cs:
IOptionsMonitor<SampleOptions>到.ctorSampleOptions发生更改时调用。IOptionsMonitor<SampleOptions>.OnChange这是文件。
应用程序设置.json
{
"Logging": {
"LogLevel": {
"Default": "Information"
}
},
"SampleOptions": {
"SampleStringKey": "Sample value",
"SampleIntegerKey": 42
}
}
Run Code Online (Sandbox Code Playgroud)
示例选项.cs
namespace WinFormsAppNet6;
public class SampleOptions
{
public string SampleStringKey { get; set; } = "N/A";
public int SampleIntegerKey { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
程序.cs
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace WinFormsAppNet6;
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static async Task Main() // <-- 'async Task' instead of 'void'
{
// To customize application configuration such as
// set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
using IHost host = CreateHost();
await host.StartAsync();
IHostApplicationLifetime lifetime =
host.Services.GetRequiredService<IHostApplicationLifetime>();
using (IServiceScope scope = host.Services.CreateScope())
{
var mainForm = scope.ServiceProvider.GetRequiredService<MainForm>();
Application.Run(mainForm);
}
lifetime.StopApplication();
await host.WaitForShutdownAsync();
}
private static IHost CreateHost()
{
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddSingleton<MainForm>();
builder.Services.Configure<SampleOptions>(
builder.Configuration.GetSection(nameof(SampleOptions))
);
return builder.Build();
}
}
Run Code Online (Sandbox Code Playgroud)
MainForm.cs
控制:
Button: UpdateConfigurationButtonButton: ExitButtonRichTextBox: AppLogusing System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Windows.Forms;
using Microsoft.Extensions.Options;
namespace WinFormsAppNet6;
public partial class MainForm : Form
{
private readonly IOptionsMonitor<SampleOptions> optionsMonitor;
private readonly JsonSerializerOptions jsonSerializerOptions =
new(JsonSerializerDefaults.Web)
{
WriteIndented = true
};
public MainForm(IOptionsMonitor<SampleOptions> optionsMonitor)
{
InitializeComponent();
this.optionsMonitor = optionsMonitor;
optionsMonitor.OnChange(OnOptionsChange);
LogOptions(optionsMonitor.CurrentValue);
}
private void OnOptionsChange(SampleOptions options)
{
LogOptions(options);
}
private void LogOptions(
SampleOptions options,
[CallerMemberName] string? callerMemberName = null
)
{
AppendLog(
Environment.NewLine + JsonSerializer.Serialize(options),
callerMemberName
);
}
private void AppendLog(
string message,
[CallerMemberName] string? callerMemberName = null
)
{
if (AppLog.InvokeRequired)
{
AppLog.Invoke(() => AppendLog(message, callerMemberName));
return;
}
AppLog.AppendText(
$"{DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.ffffff} [{nameof(MainForm)}]::[{callerMemberName ?? "Unknown"}] {message}{Environment.NewLine}"
);
}
private void UpdateConfigurationButton_Click(object sender, EventArgs e)
{
const string AppSettingsJsonFileName = "appsettings.json";
if (!File.Exists(AppSettingsJsonFileName))
{
AppendLog(
$"{nameof(FileNotFoundException)}: {AppSettingsJsonFileName}"
);
return;
}
string jsonContent = File.ReadAllText(AppSettingsJsonFileName);
JsonNode? rootNode = JsonNode.Parse(jsonContent);
if (rootNode is null)
{
AppendLog($"{nameof(JsonException)}: File parse failed.");
return;
}
AppendLog(
$"Finding key: {nameof(SampleOptions)}:{nameof(SampleOptions.SampleStringKey)}"
);
JsonObject rootObject = rootNode.AsObject();
JsonObject? optionsObject = rootObject[nameof(SampleOptions)]?.AsObject();
if (optionsObject is null)
{
AppendLog(
$"{nameof(KeyNotFoundException)}: {nameof(SampleOptions)}:{nameof(SampleOptions.SampleStringKey)}"
);
return;
}
AppendLog(
$"Updating key: {nameof(SampleOptions)}:{nameof(SampleOptions.SampleStringKey)}"
);
optionsObject[nameof(SampleOptions.SampleStringKey)] =
JsonValue.Create(
$"Value modified at {DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.ffffff}"
);
AppendLog($"Saving file: {AppSettingsJsonFileName}");
using var stream =
new FileStream(
AppSettingsJsonFileName,
FileMode.OpenOrCreate,
FileAccess.Write,
FileShare.None
);
jsonContent = rootObject.ToJsonString(jsonSerializerOptions);
stream.Write(Encoding.UTF8.GetBytes(jsonContent));
stream.Flush();
}
private void ExitButton_Click(object? sender, EventArgs e)
{
Application.Exit();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3124 次 |
| 最近记录: |