gpt4 book ai didi

c# - ChangeToken.OnChange 不会在自定义配置提供程序上触发

转载 作者:太空宇宙 更新时间:2023-11-03 16:59:24 25 4
gpt4 key购买 nike

我将尝试创建将从数据库中获取 key 的自定义配置提供程序。正如手册中所写,我创建了这个提供者并且它工作正常。所有 key 都在启动时加载并且一切正常。

但现在我正在尝试使用 IOptionsSnapshot 并在 key 更改时从数据库重新加载 key 。但是没有任何反应。

谁能告诉我哪里出了问题?这是我的代码:

public class EFConfigProvider : ConfigurationProvider
{
private DateTime lastLoaded;
public EFConfigProvider(Action<DbContextOptionsBuilder> optionsAction)
{
OptionsAction = optionsAction;
lastLoaded = DateTime.Now;
ChangeToken.OnChange(
() => Watch(),
() => {
Thread.Sleep(250);
this.Load();
});
}

public new IChangeToken GetReloadToken()
{
return Watch();
}

Action<DbContextOptionsBuilder> OptionsAction { get; }

// Load config data from EF DB.
public override void Load()
{
this.Data.Clear();

var builder = new DbContextOptionsBuilder<ConfigContext>();
OptionsAction(builder);

using (var dbContext = new ConfigContext(builder.Options))
{
// Save Load Fact
dbContext.SaveLoadFact();
// Load Partners Settings
GetPartners(dbContext);
}
}

private IChangeToken Watch()
{
return new DatabaseChangeToken();
}
}

public class DatabaseChangeToken : IChangeToken
{
public bool HasChanged
{
get
{
return true;
}
}
public bool ActiveChangeCallbacks => false;

public IDisposable RegisterChangeCallback(Action<object> callback, object state) => EmptyDisposable.Instance;

internal class EmptyDisposable : IDisposable
{
public static EmptyDisposable Instance { get; } = new EmptyDisposable();
private EmptyDisposable() { }
public void Dispose() { }
}
}

我做了什么来开始工作:

  1. 我在类 EFConfigProvider 变量中添加
private ConfigurationReloadToken _reloadToken = new ConfigurationReloadToken();
  1. 我在构造函数中添加
// Start Periodic task to refresh the DB
PeriodicTask.Run(() =>
{
//Refresh();
OnReload();
}, TimeSpan.FromSeconds(reload));
  1. 我为 periodTask 添加类
public class PeriodicTask
{
public static async Task Run(Action action, TimeSpan period, CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
await Task.Delay(period, cancellationToken);

if (!cancellationToken.IsCancellationRequested)
action();
}
}

public static Task Run(Action action, TimeSpan period)
{
return Run(action, period, CancellationToken.None);
}
}
  1. 在重新加载时添加方法
protected new void OnReload()
{
var previousToken = Interlocked.Exchange(ref _reloadToken, new ConfigurationReloadToken());
previousToken.OnReload();
}
  1. 添加使用更改 token 的更改
  ChangeToken.OnChange(
() => { return this._reloadToken; },
() => {
Thread.Sleep(250);
this.Load();
});

最佳答案

更新:我发现重写 OnReload() 会破坏更改通知(我使用的是 OptionsMonitor,它没有看到变化)。所以我改变了我的实现不这样做。它调用默认的 OnReload() 来处理 OptionsMonitor 的更改通知。


您更新后的实现确实帮了我大忙,非常感谢!

但与其使用自定义的 PeriodicTask,不如使用 Timer .效果是一样的。

这是我的实现,每 5 分钟重新加载一次数据:

using System;
using System.Linq;
using System.Threading;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
using Timer = System.Timers.Timer;

namespace MyProject.Classes.Configuration {
public class MyConfigProvider : ConfigurationProvider {
private readonly DbContextOptions<MyDbContext> _dbOptions;
private readonly Timer _reloadTimer = new Timer();
private ConfigurationReloadToken _reloadToken = new ConfigurationReloadToken();

public MyConfigProvider(Action<DbContextOptionsBuilder> dbOptionsAction) {
var builder = new DbContextOptionsBuilder<MyDbContext>();
dbOptionsAction(builder);
_dbOptions = builder.Options;

_reloadTimer.AutoReset = false;
_reloadTimer.Interval = TimeSpan.FromMinutes(5).TotalMilliseconds;
_reloadTimer.Elapsed += (s, e) => { Load(); };
}

public override void Load() {
try {
using (var db = new MyDbContext(_dbOptions)) {
var settings = db.Settings.AsNoTracking().ToList();
Data.Clear();

foreach (var s in settings) {
Data.Add(s.Name, s.Value);
}
}
OnReload();
} finally {
_reloadTimer.Start();
}
}
}
}

关于c# - ChangeToken.OnChange 不会在自定义配置提供程序上触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48770143/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com