当前位置: 首页 > news >正文

利用接口中的静态虚拟成员实现自定义配置节

利用接口中的静态虚拟成员实现自定义配置节

C# 11引入了一项新特性——接口中的静态虚拟成员。该特性的主要动机是支持通用数学算法。提到数学可能会让一些人忽略这个特性,但实际上它在其他场景中也很有用。

例如,我利用这个特性清理了注册和使用自定义配置节类型的方式。

自定义配置节

作为回顾,让我们看看自定义配置节。假设您想在appSettings.json中配置API客户端。您可以将配置节映射到类型。例如,以下是我某个项目中的appSettings.json文件。

{"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*","OpenAI": {"ApiKey": "Set this in User Secrets","OrganizationId": "{Set this to your org id}","Model": "gpt-4","EmbeddingModel": "text-embedding-3-large"}
}

与其通过IConfiguration API逐个读取"OpenAI"设置,我更倾向于将其映射到一个类型。

public class OpenAIOptions {public string? ApiKey { get; init; }public string? OrganizationId { get; init; }public string Model { get; init; } = "gpt-3.5-turbo";public string EmbeddingModel { get; init; } = "text-embedding-ada-002";
}

在Program.cs中,我可以配置这个映射。

builder.Configuration.Configure<OpenAIOptions>(builder.Configuration.GetSection("OpenAI"));

配置完成后,我可以将IOptions注入到通过依赖解析解析的任何类中,并以强类型方式访问配置节属性。

using Microsoft.Extensions.Options;public class OpenAIClient(IOptions<OpenAIOptions> options) {string? ApiKey => options.Value.ApiKey;string? Model => options.Value.Model;// ...
}

有时,由于某种原因无法注入IOptions。您可以通过IConfiguration获取它。

Configuration.GetSection("OpenAI").Get<OpenAIOptions>()

静态虚拟接口来清理

这一切都很好,但当您有多个配置类时,会有些重复。我希望构建一个更基于约定的方法。这就是静态虚拟成员接口派上用场的地方。

首先,为所有配置节定义一个接口。

public interface IConfigOptions
{static abstract string SectionName { get; }
}

注意,有一个名为SectionName的静态抽象字符串属性。这是静态虚拟成员。任何实现此接口的类型都必须实现静态SectionName属性。

现在,我将在配置类中实现该接口。

public class OpenAIOptions : IConfigOptions {public static string SectionName => "OpenAI";public string? ApiKey { get; init; }public string? OrganizationId { get; init; }public string Model { get; init; } = "gpt-3.5-turbo";public string EmbeddingModel { get; init; } = "text-embedding-ada-002";
}

有了这个,我可以实现一个扩展方法来在注册配置节类型时访问SectionName。

public static class OptionsExtensions {public static IHostApplicationBuilder Configure<TOptions>(this IHostApplicationBuilder builder)where TOptions : class, IConfigOptions{var section = builder.Configuration.GetSection(TOptions.SectionName);builder.Services.Configure<TOptions>(section);return builder;}public static TOptions? GetConfigurationSection<TOptions>(this IHostApplicationBuilder builder)where TOptions : class, IConfigOptions{return builder.Configuration.GetSection(TOptions.SectionName).Get<TOptions>();}
}

现在,使用这个方法,我可以这样注册配置节:

builder.Configure<OpenAIOptions>();

当您有多个配置节需要配置时,注册代码看起来简洁明了。

例如,在一个项目中,我有这样的部分:

builder.Configure<OpenAIOptions>().Configure<GitHubOptions>().Configure<GoogleOptions>().Configure<WeatherOptions>()

结论

敏锐的读者会注意到,我不需要在这里使用静态虚拟成员。我本可以通过使用反射从类型名称中提取配置节名称来构建基于约定的方法。确实如此,但代码不如这种方法紧凑。此外,有时您可能希望类型名称与节名称不同。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

公众号二维码

公众号二维码

http://www.zskr.cn/news/14388.html

相关文章:

  • 【Rust GUI开发入门】编写一个本地音乐播放器(10. 拼装UI组件) - Jordan
  • 【Leetcode】随笔 - 详解
  • STM32 智能垃圾桶项目笔记(一):超声波模块(HC-SR04)原理与驱动实现 - 教程
  • 威佐夫博弈(Wythoff‘s Game)
  • Python 正则表达式实战:一文搞定文本处理
  • 详细介绍:Music Tag Web 怎么安装 ffmpeg?
  • 作业-1
  • 2025 年快速卷帘门品牌最新推荐排行榜:聚焦智能定制与高效供货,精选快速卷帘门实力厂家
  • 植物大战僵尸融合版下载安装教程【PC/安卓/iOS 完整攻略 + 常见问题解决】 - 详解
  • 两场div3 逆向思维
  • 题解:B4410 [GESP202509 一级] 金字塔
  • 2025.9.30总结 - A
  • Java入门级教程21——Java 缓存技术、RMI远程办法调用、多线程分割大档案
  • java从word模板生成.doc和.wps文件
  • 函数-参数+作用域
  • 思路探索:当大型语言模型遇见数据分析的现实挑战 - 教程
  • 读博期间的工作节奏与身心状态管理经验总结
  • 【Rust GUI开发入门】编写一个本地音乐播放器(7. 制作歌词显示面板) - Jordan
  • 【Nordic】nRF9151的SLM例程常用AT指令说明
  • Codeforces 2149G Buratsuta 3 题解 [ 蓝 ] [ 摩尔投票 ] [ 线段树 ] [ 随机化 ] [ 主席树 ] [ 根号分治 ]
  • 2025 年最新推荐软件开发机构榜:聚焦微服务架构与 724 小时服务的优质厂商精选指南人力资源管理系统/资产管理系统/数据中台管理系统/流程管理系统软件开发公司推荐
  • 最新WTAPI开发微信机器人教程说明
  • 2025 年最新制氮机厂家权威推荐排行榜:聚焦行业优质厂商综合实力,助力企业精准选购优质设备制氮机产生氮气/氮气纯化/设备改造/维修/保养/半导体用制氮机厂家推荐
  • 2025 年除湿机厂家最新权威推荐排行榜:实力厂家技术口碑评测及场景适配选购指南吊顶/泳池/车库/防爆/调温/新风除湿机厂家推荐
  • 2025 年液氨蒸发器厂家联系方式,众众电热:多领域加热设备供应与定制化解决方案提供商
  • ClickHouse 窗口函数详解:告别 GROUP BY 的局限性,实现灵活数据分析 - 若
  • Vue3 使用注意事项
  • java 解析json字符串,获取特定的字段值,JsonObject
  • Java 一行一行的读取文本,小Demo 大学问
  • 数字化转型业务流程总览图