在 .net 核心中通过 worker posting 发送多个 appsettings.json 值到 API 的简单方法?
Easy way to send multiple appsettings.json values through worker posting to API in .net core?
我正在 .Net Core 3.1 中构建 C# Windows 服务 API 轮询应用程序。这将在服务器上 运行 24/7 并每 5 分钟轮询一次。
我想要一种更简单的方法来通过我的 API post 调用发送参数,方法是直接从我的 appsettings.json 的主体发送值,而不是创建新的 classes 和我将轮询的每个对象的强类型。
我的应用程序当前使用一个 appsettings 对象,代码如下:
appsettings.json
"ReceiptSettings": {
"select_topx": "100",
"tran_type": "REC",
"sub_type": "PO",
"max_age_min": "10000",
"integration_name": "ERP"
}
工人:
public IConfiguration _configuration { get; private set; }
...
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Hosted Service running.");
_timer = new Timer(DoWork, Task.CompletedTask, TimeSpan.Zero,
TimeSpan.FromMinutes(5));
await Task.CompletedTask;
}
private async void DoWork(object state)
{
// Keep garbage collector from collecting and stopping timer
GC.KeepAlive(_timer);
// Don't let timer execute again if we are still processing last iteration
if (Monitor.TryEnter(_locker))
{
try
{
RunPoller();
}
finally
{
Monitor.Exit(_locker);
}
}
}
private async void RunPoller()
{
var count = Interlocked.Increment(ref executionCount);
// Do long running work here
_logger.LogInformation($"Polling started. Iteration: {count}");
await Task.Run(() => RunPoller.Run(_logger, _apiSettings, _configuration));
}
运行轮询器:
public static IConfiguration _iConfiguration { get; private set; }
public static async Task Run(ILogger<Worker> logger, IOptions<APIConfiguration> apiSettings, IConfiguration configuration)
{
...
try
{
Dictionary<string, object> settings = _config
.GetSection("ReceiptSettings")
.Get<Dictionary<string, object>>();
string json = JsonConvert.SerializeObject(_settings);
var payload = new StringContent(json, Encoding.UTF8, "application/json");
...
}
...
我想重构它以遍历 PollingSettings 对象,根据值:
为 PollingSettings 中的每个设置创建一个新线程
"PollingSettings": {
"ReceiptSettings": {
"select_topx": "100",
"tran_type": "REC",
"sub_type": "PO",
"max_age_min": "10000",
"integration_name": "ERP"
},
"InventorySettings": {
"select_topx": "100",
"tran_type": "IN",
"sub_type": "ADJ",
"mark_pickup_id": "1"
}
我已经有了强类型的 apiSettings 并且可以做到。但是我必须在整个对象和 Visual Studio 中的 classes 中坚持更改。如果我要通过这种方法动态发送它们,那么我可以在记事本中打开 appsettings.json 文件并在更短的时间内修改参数。
我已经试过了,但是我得到了空值错误,而且第一次迭代没有触发 RunPoller class:
private async void DoWork(object state)
{
// Keep garbage collector from collecting and stopping timer
GC.KeepAlive(_timer);
var pollingConfigs = Configuration.GetSection("PollingSettings").GetChildren();
// Don't let timer execute again if we are still processing last iteration
if (Monitor.TryEnter(_locker))
{
try
{
foreach (var setting in pollingConfigs)
{
Dictionary<string, object> settings = Configuration
.GetSection(setting.Key)
.Get<Dictionary<string, object>>();
RunPoller(settings);
}
}
finally
{
Monitor.Exit(_locker);
}
}
}
private async void RunPoller(Dictionary<string, object> settings)
{
// Do long running work here
_logger.LogInformation($"Polling started. Iteration: {count}");
await Task.Run(() => RunPoller.Run(_logger, _apiSettings, settings));
}
(将用于设置的 DI 保留到 RunPoller.Run,为简洁起见删除了代码。)
有什么方法可以正确做到这一点吗?
对于现有的代码,您可以只更改获取子部分的路径,如以下代码:
1 - 将 Key
更改为 Path
以获得 .GetSection(setting.Key)
:
var pollingConfigs = Configuration.GetSection("PollingSettings").GetChildren();
// Don't let timer execute again if we are still processing last iteration
if (Monitor.TryEnter(_locker))
{
try
{
foreach (var setting in pollingConfigs)
{
Dictionary<string, object> settings = Configuration
.GetSection(setting.Path)
.Get<Dictionary<string, object>>();
RunPoller(settings);
}
}
finally
{
Monitor.Exit(_locker);
}
}
2 - 您也可以使用此解决方案:
2.1 获取Dictionary<string, object>
:
的列表
var pollingConfigs = _configuration.GetSection("PollingSettings")
.GetChildren()
.Select(y => y.Get<Dictionary<string, object>>());
2.2 并在循环中,直接使用列表的值:
foreach (Dictionary<string, object> setting in pollingConfigs)
{
RunPoller(setting);
}
希望对您有所帮助。
我正在 .Net Core 3.1 中构建 C# Windows 服务 API 轮询应用程序。这将在服务器上 运行 24/7 并每 5 分钟轮询一次。
我想要一种更简单的方法来通过我的 API post 调用发送参数,方法是直接从我的 appsettings.json 的主体发送值,而不是创建新的 classes 和我将轮询的每个对象的强类型。
我的应用程序当前使用一个 appsettings 对象,代码如下:
appsettings.json
"ReceiptSettings": {
"select_topx": "100",
"tran_type": "REC",
"sub_type": "PO",
"max_age_min": "10000",
"integration_name": "ERP"
}
工人:
public IConfiguration _configuration { get; private set; }
...
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Hosted Service running.");
_timer = new Timer(DoWork, Task.CompletedTask, TimeSpan.Zero,
TimeSpan.FromMinutes(5));
await Task.CompletedTask;
}
private async void DoWork(object state)
{
// Keep garbage collector from collecting and stopping timer
GC.KeepAlive(_timer);
// Don't let timer execute again if we are still processing last iteration
if (Monitor.TryEnter(_locker))
{
try
{
RunPoller();
}
finally
{
Monitor.Exit(_locker);
}
}
}
private async void RunPoller()
{
var count = Interlocked.Increment(ref executionCount);
// Do long running work here
_logger.LogInformation($"Polling started. Iteration: {count}");
await Task.Run(() => RunPoller.Run(_logger, _apiSettings, _configuration));
}
运行轮询器:
public static IConfiguration _iConfiguration { get; private set; }
public static async Task Run(ILogger<Worker> logger, IOptions<APIConfiguration> apiSettings, IConfiguration configuration)
{
...
try
{
Dictionary<string, object> settings = _config
.GetSection("ReceiptSettings")
.Get<Dictionary<string, object>>();
string json = JsonConvert.SerializeObject(_settings);
var payload = new StringContent(json, Encoding.UTF8, "application/json");
...
}
...
我想重构它以遍历 PollingSettings 对象,根据值:
为 PollingSettings 中的每个设置创建一个新线程"PollingSettings": {
"ReceiptSettings": {
"select_topx": "100",
"tran_type": "REC",
"sub_type": "PO",
"max_age_min": "10000",
"integration_name": "ERP"
},
"InventorySettings": {
"select_topx": "100",
"tran_type": "IN",
"sub_type": "ADJ",
"mark_pickup_id": "1"
}
我已经有了强类型的 apiSettings 并且可以做到。但是我必须在整个对象和 Visual Studio 中的 classes 中坚持更改。如果我要通过这种方法动态发送它们,那么我可以在记事本中打开 appsettings.json 文件并在更短的时间内修改参数。
我已经试过了,但是我得到了空值错误,而且第一次迭代没有触发 RunPoller class:
private async void DoWork(object state)
{
// Keep garbage collector from collecting and stopping timer
GC.KeepAlive(_timer);
var pollingConfigs = Configuration.GetSection("PollingSettings").GetChildren();
// Don't let timer execute again if we are still processing last iteration
if (Monitor.TryEnter(_locker))
{
try
{
foreach (var setting in pollingConfigs)
{
Dictionary<string, object> settings = Configuration
.GetSection(setting.Key)
.Get<Dictionary<string, object>>();
RunPoller(settings);
}
}
finally
{
Monitor.Exit(_locker);
}
}
}
private async void RunPoller(Dictionary<string, object> settings)
{
// Do long running work here
_logger.LogInformation($"Polling started. Iteration: {count}");
await Task.Run(() => RunPoller.Run(_logger, _apiSettings, settings));
}
(将用于设置的 DI 保留到 RunPoller.Run,为简洁起见删除了代码。)
有什么方法可以正确做到这一点吗?
对于现有的代码,您可以只更改获取子部分的路径,如以下代码:
1 - 将 Key
更改为 Path
以获得 .GetSection(setting.Key)
:
var pollingConfigs = Configuration.GetSection("PollingSettings").GetChildren();
// Don't let timer execute again if we are still processing last iteration
if (Monitor.TryEnter(_locker))
{
try
{
foreach (var setting in pollingConfigs)
{
Dictionary<string, object> settings = Configuration
.GetSection(setting.Path)
.Get<Dictionary<string, object>>();
RunPoller(settings);
}
}
finally
{
Monitor.Exit(_locker);
}
}
2 - 您也可以使用此解决方案:
2.1 获取Dictionary<string, object>
:
var pollingConfigs = _configuration.GetSection("PollingSettings")
.GetChildren()
.Select(y => y.Get<Dictionary<string, object>>());
2.2 并在循环中,直接使用列表的值:
foreach (Dictionary<string, object> setting in pollingConfigs)
{
RunPoller(setting);
}
希望对您有所帮助。