net core自定义 Configuration Provider

创建CustomConfigurationProvider

首先,我们需要创建一个自定义的 ConfigurationSource 和 ConfigurationProvider 来支持配置文件的读取和监控。

public class CustomConfigurationSource : IConfigurationSource
{
    public string FilePath { get; }

    public CustomConfigurationSource(string filePath)
    {
        FilePath = filePath;
    }

    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new CustomConfigurationProvider(this);
    }
}

public class CustomConfigurationProvider : ConfigurationProvider, IDisposable
{
    private readonly string _filePath;
    private FileSystemWatcher _fileWatcher;

    public CustomConfigurationProvider(CustomConfigurationSource source)
    {
        _filePath = source.FilePath;
        Load();

        _fileWatcher = new FileSystemWatcher(Path.GetDirectoryName(_filePath))
        {
            Filter = Path.GetFileName(_filePath),
            NotifyFilter = NotifyFilters.LastWrite
        };
        _fileWatcher.Changed += OnChanged;
        _fileWatcher.EnableRaisingEvents = true;
    }

    private void OnChanged(object sender, FileSystemEventArgs e)
    {
        Load();
        OnReload(); // 通知配置系统已更新
    }

    public override void Load()
    {
        // 加载配置数据
        Data = JsonConfigurationFileParser.Parse(File.ReadAllText(_filePath));
    }

    public void Dispose()
    {
        _fileWatcher?.Dispose();
    }
}

public class CustomConfigurationProvider : ConfigurationProvider
{
    private readonly string _filePath;

    public CustomConfigurationProvider(string filePath)
    {
        _filePath = filePath;
    }

    public override void Load()
    {
        // Load configuration data from the file
        Data = LoadConfigurationFromFile(_filePath);
    }

    private IDictionary<string, string> LoadConfigurationFromFile(string filePath)
    {
        // Implement logic to load data from the file
        var data = new Dictionary<string, string>();
        // Example: data["Key"] = "Value";
        return data;
    }
}

创建 Background Service

public class ConfigurationUpdateService : BackgroundService
{
    private readonly IConfigurationRoot _configurationRoot;
    private readonly TimeSpan _updateInterval = TimeSpan.FromMinutes(5);

    public ConfigurationUpdateService(IConfigurationRoot configurationRoot)
    {
        _configurationRoot = configurationRoot;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // Check for updates and reload the configuration if needed
            ReloadConfigurationIfChanged();

            // Wait for the next check
            await Task.Delay(_updateInterval, stoppingToken);
        }
    }

    private void ReloadConfigurationIfChanged()
    {
        // Assuming the custom provider is used
        var customProvider = _configurationRoot.Providers
            .OfType<CustomConfigurationProvider>()
            .FirstOrDefault();

        if (customProvider != null)
        {
            customProvider.Load();
            customProvider.OnReload();
        }
    }
}

注册服务和配置 在program.cs里面

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // Register the custom configuration source
        builder.Configuration.Add(new CustomConfigurationSource("path/to/config.json"));

        // Register the background service
        builder.Services.AddHostedService<ConfigurationUpdateService>();

        var app = builder.Build();

        app.Run();
    }
}

配置重新加载:当后台服务检测到更改时,它会在提供程序上调用 Load() 以刷新数据,然后触发 OnReload() 以通知配置系统。

使用IOptionsMonitor

public class MyOptions
{
    public string Setting1 { get; set; }
    public int Setting2 { get; set; }
}
{
  "MyOptions": {
    "Setting1": "Value1",
    "Setting2": 42
  }
}

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // Register options and bind them to configuration section
        builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions"));

        var app = builder.Build();

        app.Run();
    }
}


public class MyService
{
    private readonly IOptionsMonitor<MyOptions> _optionsMonitor;

    public MyService(IOptionsMonitor<MyOptions> optionsMonitor)
    {
        _optionsMonitor = optionsMonitor;

        // Subscribe to changes
        _optionsMonitor.OnChange(OnOptionsChanged);

        // Access the current value
        var currentOptions = _optionsMonitor.CurrentValue;
        Console.WriteLine($"Initial Setting1: {currentOptions.Setting1}");
        Console.WriteLine($"Initial Setting2: {currentOptions.Setting2}");
    }

    private void OnOptionsChanged(MyOptions options)
    {
        // This method is called whenever the options change
        Console.WriteLine($"Updated Setting1: {options.Setting1}");
        Console.WriteLine($"Updated Setting2: {options.Setting2}");
    }
}

  1. IOptions
    用途: 提供一种简单的方式来访问应用程序的配置选项,适合那些配置在应用程序生命周期内不会改变的场景。

特点:

IOptions 仅提供配置选项的一个单一快照(snapshot)。
配置选项在应用启动时加载,并在应用运行期间保持不变。
示例:

Copy code
public class MyService
{
    private readonly MyOptions _options;

    public MyService(IOptions<MyOptions> options)
    {
        _options = options.Value;
        Console.WriteLine($"Setting1: {_options.Setting1}");
        Console.WriteLine($"Setting2: {_options.Setting2}");
    }
}
  1. IOptionsSnapshot
    用途: 提供一次性(per-request)的配置选项快照,通常用于需要在每个请求中读取当前配置状态的场景。

特点:

适用于基于依赖注入的作用域,例如在 ASP.NET Core 中每个 HTTP 请求期间的配置。
在每个请求的生命周期内,可以获取配置的最新值。
示例:

public class MyService
{
    private readonly MyOptions _options;

    public MyService(IOptionsSnapshot<MyOptions> options)
    {
        _options = options.Value;
        Console.WriteLine($"Setting1: {_options.Setting1}");
        Console.WriteLine($"Setting2: {_options.Setting2}");
    }
}

使用 IOptionsSnapshot 会在每次请求期间重新计算并获取配置值。
3. IOptionsFactory
用途: 负责创建 T 类型的选项实例。通常不直接使用,而是由框架在内部使用来创建选项实例。

特点:

可以通过自定义 IOptionsFactory 来控制如何创建配置选项对象。
示例:

大多数情况下,不需要直接使用或实现 IOptionsFactory,因为它通常是由 IOptions 或 IOptionsSnapshot 自动处理的。
4. IOptionsValidator
用途: 用于验证配置选项是否符合某些规则或要求。可以在选项加载后自动验证其有效性。

特点:

允许你在选项初始化时进行验证,并抛出异常或生成错误消息。
示例:

可以自定义实现 IOptionsValidator 并注册到服务中,以确保选项在应用启动时是有效的。
5. IOptionsChangeTokenSource
用途: 提供一个 IChangeToken,用于检测配置变化。

特点:

与 IOptionsMonitor 一起使用,帮助监视配置源的更改。
示例:

通常在自定义配置源中使用,以便在配置数据发生变化时,触发 IOptionsMonitor 的重新加载。
6. IOptionsMonitorCache
用途: 管理 IOptionsMonitor 的缓存。允许你自定义选项的缓存行为。

特点:

提供一种方法来清除缓存并强制重新加载选项。
示例:

在某些场景下,你可能需要手动清除缓存,以便获取最新的配置数据。
什么时候选择使用哪个类型?
IOptions: 适用于配置在应用程序生命周期内不需要改变的场景。
IOptionsSnapshot: 适用于每个请求可能需要不同配置快照的场景(通常在 ASP.NET Core Web 应用中使用)。
IOptionsMonitor: 适用于需要实时监控配置变化,并动态响应的场景。
IOptionsFactory 和 IOptionsMonitorCache: 适用于需要自定义配置选项创建或缓存行为的高级场景。
这些选项机制使得 .NET Core 的配置系统非常灵活,可以满足从简单到复杂的配置需求。

posted @ 2024-08-29 10:30  Josen_Earth  阅读(31)  评论(0编辑  收藏  举报