Add XCode skills for entity caching, ORM, and sharding ETL
|
---
name: config-provider-system
description: >
在 .NET 应用ä¸è®¾è®¡æˆ–使用统一é…ç½®æä¾›è€…架构,涵盖强类型å•例é…ç½®ã€å¤šæ ¼å¼æ–‡ä»¶ï¼ˆXML/JSON/INI)ã€
远程é…ç½®ä¸å¿ƒï¼ˆHTTP/Apollo)ã€çƒæ›´æ–°ç»‘定ã€å†’å·åˆ†éš”多级 Key 访问,以åŠå‘½ä»¤è¡Œå‚æ•°è§£æžã€‚
适用于é…置系统设计ã€IConfigProvider 实现ã€ConfigAttribute 定义,以åŠä»£ç 审查任务。
argument-hint: >
è¯´æ˜Žä½ çš„é…置场景:本地文件还是远程é…ç½®ä¸å¿ƒï¼›æ˜¯å¦éœ€è¦çƒæ›´æ–°ï¼›
强类型å•例 (Config<T>) 还是手动 IConfigProviderï¼›å•环境还是多 Scope。
---
# é…ç½®æä¾›è€…系统设计技能
## 适用场景
- 为应用程åºå®šä¹‰å¼ºç±»åž‹é…置对象,并希望自动与文件(XML/JSON/INI)åŒå‘åŒæ¥ã€‚
- 使用远程é…ç½®ä¸å¿ƒï¼ˆå¦‚星尘ã€Apollo)统一管ç†å¤šæœåŠ¡é…置,需è¦è½®è¯¢çƒæ›´æ–°å’Œæœ¬åœ°ç¼“å˜å…œåº•。
- 在åŒä¸€è¿›ç¨‹ä¸åŒæ—¶ä½¿ç”¨å¤šç§é…ç½®æ¥æºï¼Œéœ€è¦ä¼˜å…ˆçº§ç»„åˆæˆ–命å空间隔离。
- è§£æžå‘½ä»¤è¡Œå‚数并与é…置模型åˆå¹¶ã€‚
- 审查现有é…ç½®ä»£ç æ˜¯å¦éµå¾ªæŽ¥å£ä¼˜å…ˆã€å•例访问ã€çƒæ›´æ–°å®‰å…¨ç‰åŽŸåˆ™ã€‚
## æ ¸å¿ƒåŽŸåˆ™
1. **接å£ä¼˜å…ˆ**:所有代ç é¢å‘ `IConfigProvider` 接å£ï¼Œä¸ç›´æŽ¥ä¾èµ– `XmlConfigProvider` ç‰å…·ä½“类型;æä¾›è€…实例通过 `Config<T>.Provider` 替æ¢ï¼Œè€Œä¸æ˜¯åœ¨ä¸šåŠ¡é€»è¾‘ä¸æ‰‹åŠ¨åˆ›å»ºã€‚
2. **强类型å•例 `Config<T>`**:æ¯ç§é…置使用独立的继承类,通过 `Config<T>.Current` å•例访问;`Current` çº¿ç¨‹å®‰å…¨ï¼Œé¦–æ¬¡è®¿é—®è‡ªåŠ¨åŠ è½½æ–‡ä»¶ï¼Œæ–‡ä»¶ä¸å˜åœ¨æ—¶è¿”回默认值并写ç£ç›˜ã€‚
3. **çƒæ›´æ–° `Bind`**:`provider.Bind<T>(model, autoReload: true)` 让é…ç½®å˜æ›´è‡ªåŠ¨åŒæ¥åˆ°æ¨¡åž‹å±žæ€§ï¼›è®¢é˜…方应é¿å…在 `Changed` å›žè°ƒä¸æ‰§è¡Œè€—时逻辑。
4. **冒å·å¤šçº§ Key**:索引器 `provider["Database:ConnectionString"]` 支æŒè·¨å±‚级读写,ç‰ä»·äºŽèŠ‚ç‚¹æ ‘éåŽ†ï¼Œæ— é¡»æ‰‹åŠ¨æ‹†åˆ†è·¯å¾„ã€‚
5. **首次创建检测**:`IsNew = true` 表示é…置文件首次生æˆï¼Œå¯åœ¨ `OnLoaded()` ä¸åšé»˜è®¤å€¼åˆå§‹åŒ–å’Œ `Save()` è½ç›˜ï¼›é¿å…åœ¨æž„é€ æ—¶é€’å½’è®¿é—® `Current`。
## 执行æ¥éª¤
### 一ã€é€‰æ‹©æä¾›è€…类型
| 场景 | 推èæä¾›è€… |
|------|-----------|
| 本地 XML(默认)| `XmlConfigProvider`(`Config<T>` 默认) |
| 本地 JSON | `JsonConfigProvider` via `[Config("name", Provider = typeof(JsonConfigProvider))]` |
| 本地 INI | `IniConfigProvider` |
| 星尘/è‡ªç ”é…ç½®ä¸å¿ƒ | `HttpConfigProvider` |
| Apollo | `ApolloConfigProvider` |
| å¤šæ¥æºç»„åˆ | `CompositeConfigProvider` |
### 二ã€å®šä¹‰ `Config<T>` 强类型é…ç½®
1. 继承 `Config<TConfig>`ï¼Œæ·»åŠ `[Config("文件å")]` 特性。
2. æ¯ä¸ªå±žæ€§åŠ `[Description("...")]` 注释——`XmlConfigProvider` ä¼šæŠŠå®ƒå†™æˆ XML 注释;`JsonConfigProvider` 会忽略。
3. 在 `OnLoaded()` ä¸éªŒè¯/ä¿®æ£å—段值,确ä¿ä¸åˆæ³•å—æ®µä¸ä¼šä¼ 到业务层。
4. ä¸è¦åœ¨ç±»çš„陿€æž„é€ æˆ–å®žä¾‹æž„é€ ä¸è®¿é—® `Config<T>.Current`ï¼ˆé€’å½’åŠ è½½é™·é˜±ï¼‰ã€‚
```csharp
[Config("AppSettings")]
public class AppSettings : Config<AppSettings>
{
[Description("æœåŠ¡ç«¯å£")]
public Int32 Port { get; set; } = 8080;
[Description("调试模å¼")]
public Boolean Debug { get; set; }
protected override void OnLoaded()
{
if (Port is <= 0 or > 65535) Port = 8080;
}
}
// 使用
var cfg = AppSettings.Current;
var port = cfg.Port;
```
### 三ã€åˆ‡æ¢ä¸ºè¿œç¨‹é…ç½®ä¸å¿ƒ
```csharp
// 在应用å¯åŠ¨æœ€æ—©å¤„ï¼ˆMain / 程åºå…¥å£ï¼‰è¦†ç›– Provider
AppSettings.Provider = new HttpConfigProvider
{
Server = "http://stardust-config-center",
AppId = "my-service",
Secret = "xxx",
Scope = "production",
Period = 30, // æ¯ 30 秒轮询
CacheLevel = ConfigCacheLevel.Json // 本地明文缓å˜å…œåº•
};
```
- `Provider` 必须在首次访问 `Current` 之å‰èµ‹å€¼ï¼›èµ‹å€¼åŽç½®ç©º `_Current`(若有该 APIï¼‰é‡æ–°åŠ è½½ã€‚
- ä¸è¦åœ¨ DI å®¹å™¨æž„é€ æœŸé—´è®¿é—® `Current`,å¯èƒ½å¯¼è‡´æä¾›è€…尚未替æ¢ã€‚
### å››ã€çƒæ›´æ–°ç»‘定模型
```csharp
var provider = new HttpConfigProvider { /* ... */ };
// 绑定 POCO 模型,é…ç½®å˜æ›´è‡ªåŠ¨å†™å›žå±žæ€§
provider.Bind<FeatureFlags>(flags, autoReload: true);
// 监å¬å˜æ›´äº‹ä»¶åšé¢å¤–处ç†
provider.Changed += (_, _) =>
{
_logger.Info("é…置已更新");
RefreshCaches();
};
```
- `Bind` 会立å³ä»Ž `provider` åŠ è½½ä¸€æ¬¡ï¼ŒåŽç»é…ç½®å˜æ›´è§¦å‘ `Changed` 时自动更新属性。
- 修改绑定åŽçš„æ¨¡åž‹å±žæ€§åŽï¼Œéœ€è¦æ˜¾å¼è°ƒç”¨ `provider.Save(model)` æ‰èƒ½æŒä¹…化。
### 五ã€å‘½ä»¤è¡Œå‚æ•°è§£æž
```csharp
var parser = new CommandParser { IgnoreCase = true };
var args = parser.Parse(Environment.GetCommandLineArgs());
// --port 9090 → args["port"] = "9090"
// -v → args["v"] = null
var port = args["port"].ToInt(8080);
```
### å…ã€è‡ªå®šä¹‰ `IConfigProvider`
1. 实现 `LoadAll()`ï¼ˆä»Žæ•°æ®æº → é…ç½®æ ‘ `Root`)和 `SaveAll()`(é…ç½®æ ‘ → æ•°æ®æºï¼‰ã€‚
2. `this[key]` çš„ get 调用 `Root` çš„èŠ‚ç‚¹æ ‘é历,set å†™å›žå¯¹åº”èŠ‚ç‚¹å¹¶è§¦å‘ `Changed`。
3. å¦‚éœ€è‡ªå®šä¹‰å±žæ€§æ˜ å°„ï¼ˆå¦‚å—æ®µå转æ¢ï¼‰ï¼Œå®žçŽ°ç›®æ ‡ç±»ä¸Šçš„ `IConfigMapping` 接å£ã€‚
## é‡ç‚¹æ£€æŸ¥é¡¹
- [ ] 是å¦é¢å‘ `IConfigProvider` 接å£ï¼Œè€Œéžç›´æŽ¥ä¾èµ–具体类?
- [ ] `Config<T>.Current` 是å¦åœ¨æž„é€ å‡½æ•°å†…ï¼ˆåŒ…æ‹¬é™æ€æž„é€ ï¼‰è¢«è°ƒç”¨ï¼Œå¯¼è‡´é€’å½’ï¼Ÿ
- [ ] 远程æä¾›è€…çš„ `AppId` 是å¦å·²è®¾ç½®ï¼ˆæœªè®¾ç½®ä¼šè¢«æœåŠ¡ç«¯æ‹’ç»ï¼‰ï¼Ÿ
- [ ] çƒæ›´æ–° `Bind` åŽä¿®æ”¹å±žæ€§æ˜¯å¦é—æ¼ `Save()`?
- [ ] é…ç½®ä¿®æ”¹åŽæ˜¯å¦è°ƒç”¨äº† `SaveAll()` / `Save()`ï¼ˆå˜æ›´ä¸ä¼šè‡ªåЍæŒä¹…化到文件)?
- [ ] å¤šæ¥æºåœºæ™¯æ˜¯å¦ç”¨äº† `CompositeConfigProvider` 管ç†ä¼˜å…ˆçº§ï¼Ÿ
## è¾“å‡ºè¦æ±‚
- **é…置类**:继承 `Config<T>`,有 `[Config]` 特性ã€`[Description]` 属性注释ã€`OnLoaded` 验è¯ã€‚
- **æä¾›è€…åˆå§‹åŒ–**:在 `Main` / `Startup` æœ€æ—©å¤„å®Œæˆ `Provider` èµ‹å€¼ï¼Œä¸¥æ ¼æ—©äºŽ `Current` 的首次访问。
- **çƒæ›´æ–°**:使用 `Bind` + `Changed` äº‹ä»¶ï¼Œè€Œä¸æ˜¯è½®è¯¢ `Current` å–值对比。
- **测试**:覆盖首次创建(`IsNew`)路径ã€`OnLoaded` æ ¡éªŒã€`Changed` 回调ã€è¿œç«¯ä¸å¯ç”¨æ—¶æœ¬åœ°ç¼“å˜å…œåº•。
## å‚考资料
å‚考示例与模å¼è¯æ®è§ `references/newlife-config-patterns.md`。
|