改进 ConfigProvider 的线程安全性,使用 ConcurrentDictionary 并添加锁机制。 优化键集合处理,提升性能;修复列表映射问题,支持基础类型转换。 增强模型绑定功能,支持自动更新和线程安全回调。 新增单元测试覆盖关键场景,重构测试代码以提升可读性。 新增详细使用说明文档,帮助开发者快速上手配置系统。 移除冗余引用,保持代码整洁。
# IConfigProvider ÅäÖÃÌåϵʹÓÃ˵Ã÷
±¾Îĵµ½éÉÜ NewLife.Configuration ÅäÖÃÌåϵµÄ¼Ü¹¹¡¢Ó÷¨ÓëÀ©Õ¹µã£¬ÊÊÓÃÓÚ NewLife.Core ²Ö¿â¡£
## 1. ¼Ü¹¹¸ÅÀÀ
- ºËÐijéÏó
- `IConfigProvider`£ºÅäÖÃÌṩÕßͳһ½Ó¿Ú£¬±©Â¶¼üÖµ·ÃÎÊ¡¢Ê÷ÐζηÃÎÊ¡¢Ä£ÐÍ Load/Save/Bind¡¢±ä¸ü֪ͨ¡£
- `IConfigSection`£ºÅäÖöΣ¨½Úµã£©£¬¼ü/Öµ/×¢ÊÍÓë×Ó¼¶£¨Ê÷ÐΣ©½á¹¹¡£
- `GetConfigCallback`£º»ñÈ¡ÅäÖõÄίÍУ¬¿ÉÓÃÓÚ×¢Èëµ½ÆäËüÄ£¿éÖнøÐа´¼ü»ñÈ¡¡£
- ³éÏó»ùÀà
- `ConfigProvider`£ºÊµÏÖ `IConfigProvider` µÄ»ùÀ࣬ÌṩÀÁ¼ÓÔØ¡¢¼ü·¾¶·ÃÎÊ¡¢Ä£ÐÍÓ³Éä¡¢°ó¶¨Óë±ä¸ü֪ͨ¡¢Ä¬ÈÏÌṩÕß×¢²áÓ빤³§·½·¨¡£
- `FileConfigProvider`£ºÎļþÐÍÌṩÕß»ùÀ࣬·â×°Îļþ¶Áд¡¢ÂÖѯÈȼÓÔØ£¨`TimerX`£©¡£
- ¾ßÌåʵÏÖ
- `XmlConfigProvider`£ºXML Îļþ¡£
- `InIConfigProvider`£ºINI Îļþ¡£
- `JsonConfigProvider`£ºJSON Îļþ£¨Ö§³Ö×¢Ê͵ÄÔ¤´¦Àí£©¡£
- `HttpConfigProvider`£ºÅäÖÃÖÐÐÄ£¨Ðdz¾µÈ£©£¬´ø±¾µØ»º´æ¡¢°æ±¾ÓëÔöÁ¿Éϱ¨£¬Ö§³Ö¶¨Ê±Ë¢Ð¡£
- `ApolloConfigProvider`£ºÕë¶Ô Apollo µÄÊÊÅ䣨ÃüÃû¿Õ¼ä¾ÛºÏ¶ÁÈ¡£©¡£
- `CompositeConfigProvider`£º¸´ºÏÌṩÕߣ¬¾ÛºÏ¶à¸öÌṩÕߣ¬¶ÁÈ¡ÓÅÏÈ¡¢±£´æÖð¸ö³¢ÊÔ¡£
- ¸¨ÖúÓëÄ£ÐÍ
- `Config<T>`£ºÅäÖÃÄ£ÐÍ»ùÀ࣬`Current` ͨ¹ý±ê×¢ `ConfigAttribute` ×Ô¶¯Ñ¡ÔñÌṩÕß²¢¼ÓÔØ/°ó¶¨¡£
- `ConfigHelper`£ºÔÚÄ£ÐÍÓëÅäÖÃÊ÷Ö®¼ä½øÐÐÓ³É䣨`MapTo/MapFrom`£©£¬Ö§³ÖÊý×é¡¢`IList<T>`¡¢¸´ÔÓ¶ÔÏó¡¢×ֵ䡣
- `IConfigMapping`£º×Ô¶¨ÒåÓ³Éä½Ó¿Ú£¬Óû§¿ÉÔÚÄ£ÐÍÖÐʵÏÖÒÔ»ñµÃÍêÈ«¿ØÖƵÄÓ³ÉäÂß¼¡£
## 2. µäÐÍÓ÷¨
- ¶¨ÒåÄ£ÐÍ
```csharp
[Config("core", provider: null)] // ʹÓÃĬÈÏÌṩÕߣ¨¿ÉÈ«¾ÖÇл»£©
public class CoreConfig : Config<CoreConfig>
{
[Description("È«¾Öµ÷ÊÔ¡£XTrace.Debug")] public bool Debug { get; set; }
public string? LogPath { get; set; }
public SysConfig Sys { get; set; } = new();
}
public class SysConfig
{
[Description("ÓÃÓÚ±êʶϵͳµÄÓ¢ÎÄÃû£¬²»ÄÜÓпոñ")] public string Name { get; set; } = "";
public string? DisplayName { get; set; }
}
```
- ¼ÓÔØ/±£´æ
```csharp
var cfg = CoreConfig.Current; // Ê״λá°ó¶¨²¢×Ô¶¯ÂäÅÌ£¨Èôн¨£©
cfg.Debug = true;
cfg.Save();
```
- Ö±½ÓʹÓÃÌṩÕß
```csharp
var prv = ConfigProvider.Create("config")!; // xml ĬÈÏ .config
prv.Init("core");
prv.LoadAll();
var debug = prv["Debug"]; // ¼ü·¾¶Ö§³ÖðºÅ·Ö¸ô£º"Sys:Name"
var section = prv.GetSection("Sys:Name");
```
- °ó¶¨ÈȸüÐÂ
```csharp
var cfg = new CoreConfig();
var prv = new JsonConfigProvider { FileName = "Config/core.json" };
prv.Bind(cfg, autoReload: true); // Îļþ±ä¸ü/Ô¶¶ËÍÆËͽ«Ë¢Ð cfg
```
- ¸´ºÏÌṩÕß
```csharp
var local = new JsonConfigProvider { FileName = "Config/appsettings.json" };
var remote = new HttpConfigProvider { Server = "http://conf", AppId = "Demo" };
var composite = new CompositeConfigProvider(local, remote);
var name = composite["Sys:Name"]; // ¶Áȡʱ°´Ë³Ðò²éÕÒ
```
## 3. À©Õ¹µã
- н¨ÎļþÌṩÕߣº¼Ì³Ð `FileConfigProvider`£¬ÖØÐ´ `OnRead` Óë `GetString/OnWrite` ¼´¿É¡£
- н¨Ô¶¶ËÌṩÕߣº¼Ì³Ð `ConfigProvider`£¬ÊµÏÖ `LoadAll/SaveAll` Ó붨ʱˢУ¨¿ÉÑ¡£©¡£
- ×¢²áΪĬÈÏ£º`ConfigProvider.Register<MyProvider>("my");`£¬Ëæºóͨ¹ý `ConfigProvider.Create("my")` ʹÓá£
## 4. ÐÐΪÓëÔ¼¶¨
- ¼ü·¾¶Óï·¨£º`A:B:C` ±íʾÊ÷ÐÎÏÂ×ê¡£
- `Keys` ĬÈÏÖ»·µ»Ø¸ùϵÚÒ»²ã¼ü£»¾ßÌåʵÏֿɸ²¸Ç·µ»ØÉî²ã¼ü¼¯ºÏ¡£
- `IsNew` ÓÃÓÚָʾÅäÖÃÔ´ÊÇ·ñÊ״δ´½¨£¬`Config<T>.Current` »á¾Ý´Ë¾ö¶¨ÊÇ·ñ³Ö¾Ã»¯Ä¬ÈÏÖµ¡£
- ×¢ÊÍ£ºÄ£ÐÍÊôÐÔÉ쵀 `DescriptionAttribute/DisplayNameAttribute` »áдÈëÅäÖÃÏî×¢ÊÍ¡£
- ÁбíÓëÊý×飺`ConfigHelper` Ö§³Ö `T[]` Óë `IList<T>`£»»ùÔªÀàÐÍÔªËØ»á½øÐÐÀàÐÍת»»¡£
## 5. ±¾²Ö¿âÓÅ»¯µã£¨ÒÑ´¦Àí£©
- ÐÞ¸´£º`ConfigHelper.MapToList` ¶Ô»ùÔªÀàÐÍÔªËØ½øÐÐ `ChangeType` ת»»£¬±ÜÃâ `List<int>` ±»Ð´³É×Ö·û´®ÁÐ±í¡£
- ½¡×³ÐÔ£º`ConfigProvider.Keys` ·ÃÎÊǰµ÷Óà `EnsureLoad()`£¬±ÜÃâδ¼ÓÔØ¼´·ÃÎʵ¼ÖµĿռ¯ºÏÎóÅС£
- ²¢·¢°²È«£º`ConfigProvider` µÄ°ó¶¨¼¯ºÏ¸ÄΪ `ConcurrentDictionary`£¬·ÀÖ¹±ä¸ü֪ͨÆÚ¼äö¾ÙÒì³£¡£
## 6. ×¢ÒâÊÂÏî
- ÐÔÄÜ£º·´ÉäÓëÊ÷ÐÎÓ³Éä²»Ó¦·ÅÔÚÈȵã¸ßƵ·¾¶£»ÈçÐèÆµ·±·ÃÎÊ£¬Ç뻺´æÅäÖûòʹÓÃÇ¿ÀàÐͰ󶨡£
- Ḭ̈߳²È«£ºÄ£ÐͰó¶¨Óëˢлص÷²»ÒªÖ´ÐкÄʱ²Ù×÷£¬±ÜÃâ×èÈû֪ͨÁ´Â·¡£
- ¼æÈÝÐÔ£ºÕë¶Ô .NET Framework Óë .NET Standard ¾ùÒÑÊÊÅ䣬ÎÞÐèʹÓÃÆ½Ì¨×¨Êô API¡£
---
ÒÔÉÏ¡£
|