NavisworksTransport/src/Core/Config/ConfigManager.cs

1000 lines
36 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Tomlyn;
using Tomlyn.Model;
namespace NavisworksTransport.Core.Config
{
/// <summary>
/// 配置变更类别
/// </summary>
public enum ConfigCategory
{
None = 0,
PathEditing = 1,
Visualization = 2,
Animation = 3,
Logistics = 4,
CoordinateSystem = 5,
GridGeneration = 6,
PathPlanning = 7,
All = 99
}
/// <summary>
/// 配置变更事件参数
/// </summary>
public class ConfigurationChangedEventArgs : EventArgs
{
/// <summary>
/// 变更的配置类别
/// </summary>
public ConfigCategory ChangedCategory { get; set; }
/// <summary>
/// 是否是外部文件修改触发的变更
/// </summary>
public bool IsExternalChange { get; set; }
/// <summary>
/// 变更时间戳
/// </summary>
public DateTime ChangeTime { get; set; }
public ConfigurationChangedEventArgs(ConfigCategory category, bool isExternal = false)
{
ChangedCategory = category;
IsExternalChange = isExternal;
ChangeTime = DateTime.Now;
}
}
/// <summary>
/// 系统配置管理器
/// 负责 TOML 配置文件的读取、保存和管理
/// 支持配置变更通知机制
/// </summary>
public class ConfigManager : IDisposable
{
private static ConfigManager _instance;
private static readonly object _lock = new object();
/// <summary>
/// 单例实例
/// </summary>
public static ConfigManager Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = new ConfigManager();
}
}
}
return _instance;
}
}
/// <summary>
/// 配置变更事件
/// 订阅此事件以在配置发生变化时接收通知
/// </summary>
public event EventHandler<ConfigurationChangedEventArgs> ConfigurationChanged;
/// <summary>
/// 特定类别配置变更事件
/// 参数:发送者,(类别,事件参数)
/// </summary>
public event EventHandler<Tuple<ConfigCategory, ConfigurationChangedEventArgs>> CategoryConfigurationChanged;
/// <summary>
/// 配置文件路径
/// </summary>
public static string ConfigFilePath
{
get
{
return Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"Autodesk",
"Navisworks Manage 2026",
"plugins",
"TransportPlugin",
"config.toml"
);
}
}
/// <summary>
/// 配置目录
/// </summary>
public static string ConfigDirectory
{
get { return Path.GetDirectoryName(ConfigFilePath); }
}
/// <summary>
/// 配置模板文件路径
/// </summary>
private static string ConfigTemplatePath
{
get
{
// 从插件当前目录获取模板文件
var pluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
return Path.Combine(pluginDirectory, "resources", "default_config.toml");
}
}
private SystemConfig _currentConfig;
private string _cachedTemplateContent;
private FileSystemWatcher _fileWatcher;
private bool _isDisposed;
private bool _isReloading;
private DateTime _lastWriteTime;
private readonly object _reloadLock = new object();
// 配置兼容性检查相关
private bool _hasMissingConfigItems = false;
private List<string> _missingConfigItems = new List<string>();
/// <summary>
/// 是否存在缺失的配置项(配置文件需要升级)
/// </summary>
public bool HasMissingConfigItems => _hasMissingConfigItems;
/// <summary>
/// 缺失的配置项列表
/// </summary>
public IReadOnlyList<string> MissingConfigItems => _missingConfigItems.AsReadOnly();
/// <summary>
/// 获取配置兼容性提示信息
/// </summary>
public string GetConfigCompatibilityMessage()
{
if (!_hasMissingConfigItems || _missingConfigItems.Count == 0)
{
return null;
}
var message = $"配置文件需要升级:检测到 {_missingConfigItems.Count} 个缺失项,已使用默认值填充。\n\n";
message += "缺失项:\n";
foreach (var item in _missingConfigItems.Take(10))
{
message += $" - {item}\n";
}
if (_missingConfigItems.Count > 10)
{
message += $" ... 还有 {_missingConfigItems.Count - 10} 项\n";
}
message += "\n建议请打开【系统管理】→【参数设置】载入默认配置以升级配置文件。";
return message;
}
/// <summary>
/// 清除配置兼容性警告标志
/// </summary>
public void ClearConfigCompatibilityWarning()
{
_hasMissingConfigItems = false;
_missingConfigItems.Clear();
LogManager.Info("配置兼容性警告已清除");
}
/// <summary>
/// 是否启用文件监控(自动检测外部配置修改)
/// 默认启用
/// </summary>
public bool EnableFileWatcher { get; set; } = true;
/// <summary>
/// 文件监控防抖时间(毫秒)
/// 防止文件保存时多次触发事件
/// </summary>
public int FileWatcherDebounceMs { get; set; } = 500;
private ConfigManager()
{
_currentConfig = LoadConfigFile();
InitializeFileWatcher();
}
/// <summary>
/// 初始化文件监控
/// </summary>
private void InitializeFileWatcher()
{
try
{
if (!EnableFileWatcher)
{
LogManager.Debug("配置文件监控已禁用");
return;
}
string configDir = ConfigDirectory;
if (!Directory.Exists(configDir))
{
Directory.CreateDirectory(configDir);
}
_fileWatcher = new FileSystemWatcher(configDir, "config.toml")
{
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
EnableRaisingEvents = true
};
_fileWatcher.Changed += OnConfigFileChanged;
_fileWatcher.Renamed += OnConfigFileRenamed;
LogManager.Info($"配置文件监控已启动: {ConfigFilePath}");
}
catch (Exception ex)
{
LogManager.Error($"初始化配置文件监控失败: {ex.Message}");
// 不影响主功能,继续运行
}
}
/// <summary>
/// 配置文件变化处理
/// </summary>
private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
{
if (_isReloading || e.ChangeType != WatcherChangeTypes.Changed)
return;
lock (_reloadLock)
{
try
{
// 防抖处理:检查文件最后写入时间
var fileInfo = new FileInfo(e.FullPath);
if ((DateTime.Now - fileInfo.LastWriteTime).TotalMilliseconds > FileWatcherDebounceMs)
{
return;
}
// 避免重复加载
if ((DateTime.Now - _lastWriteTime).TotalMilliseconds < FileWatcherDebounceMs)
{
return;
}
_isReloading = true;
_lastWriteTime = DateTime.Now;
LogManager.Info("检测到配置文件外部修改,正在重新加载...");
// 延迟一点执行,确保文件写入完成
System.Threading.Thread.Sleep(100);
// 重新加载配置
ReloadInternal(isExternal: true);
}
catch (Exception ex)
{
LogManager.Error($"处理配置文件变更失败: {ex.Message}");
}
finally
{
_isReloading = false;
}
}
}
/// <summary>
/// 配置文件重命名处理
/// </summary>
private void OnConfigFileRenamed(object sender, RenamedEventArgs e)
{
if (e.Name == "config.toml")
{
LogManager.Info("配置文件被重命名/恢复,正在重新加载...");
ReloadInternal(isExternal: true);
}
}
/// <summary>
/// 获取当前配置
/// </summary>
public SystemConfig Current
{
get { return _currentConfig; }
}
/// <summary>
/// 读取配置模板文件内容
/// </summary>
private string ReadConfigTemplate()
{
if (!File.Exists(ConfigTemplatePath))
{
throw new FileNotFoundException($"配置模板文件不存在: {ConfigTemplatePath}");
}
LogManager.Info($"使用配置模板文件: {ConfigTemplatePath}");
return File.ReadAllText(ConfigTemplatePath);
}
/// <summary>
/// 加载配置文件,如果不存在则从模板创建
/// </summary>
private SystemConfig LoadConfigFile()
{
try
{
if (!File.Exists(ConfigFilePath))
{
LogManager.Info($"配置文件不存在,从模板创建: {ConfigFilePath}");
var templateContent = ReadConfigTemplate();
WriteConfigFileDirect(templateContent);
return ParseTomlToConfig(templateContent);
}
LogManager.Info($"加载配置文件: {ConfigFilePath}");
var tomlContent = File.ReadAllText(ConfigFilePath);
var config = ParseTomlToConfig(tomlContent);
LogManager.Info("配置文件加载成功");
return config;
}
catch (Exception ex)
{
LogManager.Error($"加载配置文件失败: {ex.Message}");
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
// 加载失败时使用模板中的默认配置
LogManager.Info("使用模板中的默认配置");
var templateContent = ReadConfigTemplate();
return ParseTomlToConfig(templateContent);
}
}
/// <summary>
/// 将 TOML 字符串解析为配置对象(兼容旧版本配置,使用默认值填充缺失项)
/// </summary>
private SystemConfig ParseTomlToConfig(string tomlContent)
{
var model = Toml.ToModel(tomlContent);
var config = CreateEmptyConfigObject();
var missingItems = new List<string>();
// 加载路径编辑配置
if (!model.ContainsKey("path_editing"))
{
missingItems.Add("[path_editing]");
LogManager.Warning("配置文件缺少 [path_editing] 部分,将使用默认值");
}
else
{
var pathEdit = model["path_editing"] as TomlTable;
if (pathEdit == null)
{
missingItems.Add("[path_editing] (格式错误)");
LogManager.Warning("[path_editing] 部分格式错误,将使用默认值");
}
else
{
// 使用带默认值的读取方法,不抛出异常
config.PathEditing.CellSizeMeters = GetDoubleValueWithDefault(pathEdit, "cell_size_meters", 0.5, missingItems);
config.PathEditing.MaxHeightDiffMeters = GetDoubleValueWithDefault(pathEdit, "max_height_diff_meters", 0.35, missingItems);
config.PathEditing.ObjectLengthMeters = GetDoubleValueWithDefault(pathEdit, "object_length_meters", 1.5, missingItems);
config.PathEditing.ObjectWidthMeters = GetDoubleValueWithDefault(pathEdit, "object_width_meters", 1.0, missingItems);
config.PathEditing.ObjectHeightMeters = GetDoubleValueWithDefault(pathEdit, "object_height_meters", 2.0, missingItems);
config.PathEditing.SafetyMarginMeters = GetDoubleValueWithDefault(pathEdit, "safety_margin_meters", 0.1, missingItems);
config.PathEditing.DefaultPathTurnRadiusMeters = GetDoubleValueWithDefault(pathEdit, "default_path_turn_radius", 2.5, missingItems);
config.PathEditing.ArcSamplingStepMeters = GetDoubleValueWithDefault(pathEdit, "arc_sampling_step", 0.05, missingItems);
}
}
// 加载可视化配置
if (!model.ContainsKey("visualization"))
{
missingItems.Add("[visualization]");
LogManager.Warning("配置文件缺少 [visualization] 部分,将使用默认值");
}
else
{
var visual = model["visualization"] as TomlTable;
if (visual == null)
{
missingItems.Add("[visualization] (格式错误)");
LogManager.Warning("[visualization] 部分格式错误,将使用默认值");
}
else
{
config.Visualization.MarginRatio = GetDoubleValueWithDefault(visual, "margin_ratio", 0.1, missingItems);
config.Visualization.PassageSpaceOpacity = GetDoubleValueWithDefault(visual, "passage_space_opacity", 0.4, missingItems);
}
}
// 加载动画配置
if (!model.ContainsKey("animation"))
{
missingItems.Add("[animation]");
LogManager.Warning("配置文件缺少 [animation] 部分,将使用默认值");
}
else
{
var anim = model["animation"] as TomlTable;
if (anim == null)
{
missingItems.Add("[animation] (格式错误)");
LogManager.Warning("[animation] 部分格式错误,将使用默认值");
}
else
{
config.Animation.FrameRate = GetIntValueWithDefault(anim, "frame_rate", 30, missingItems);
config.Animation.DurationSeconds = GetDoubleValueWithDefault(anim, "duration_seconds", 10.0, missingItems);
config.Animation.DetectionToleranceMeters = GetDoubleValueWithDefault(anim, "detection_tolerance_meters", 0.05, missingItems);
config.Animation.SpatialIndexCellSizeMeters = GetDoubleValueWithDefault(anim, "spatial_index_cell_size", 1.0, missingItems);
}
}
// 加载物流属性配置
if (!model.ContainsKey("logistics"))
{
missingItems.Add("[logistics]");
LogManager.Warning("配置文件缺少 [logistics] 部分,将使用默认值");
}
else
{
var logistics = model["logistics"] as TomlTable;
if (logistics == null)
{
missingItems.Add("[logistics] (格式错误)");
LogManager.Warning("[logistics] 部分格式错误,将使用默认值");
}
else
{
config.Logistics.Traversable = GetBoolValueWithDefault(logistics, "traversable", true, missingItems);
config.Logistics.Priority = GetIntValueWithDefault(logistics, "priority", 5, missingItems);
config.Logistics.HeightLimitMeters = GetDoubleValueWithDefault(logistics, "height_limit_meters", 3.0, missingItems);
config.Logistics.SpeedLimitMetersPerSecond = GetDoubleValueWithDefault(logistics, "speed_limit_meters_per_second", 0.8, missingItems);
config.Logistics.WidthLimitMeters = GetDoubleValueWithDefault(logistics, "width_limit_meters", 3.0, missingItems);
}
}
// 加载坐标系配置
if (!model.ContainsKey("coordinate_system"))
{
missingItems.Add("[coordinate_system]");
LogManager.Warning("配置文件缺少 [coordinate_system] 部分,将使用默认值");
}
else
{
var coordSys = model["coordinate_system"] as TomlTable;
if (coordSys == null)
{
missingItems.Add("[coordinate_system] (格式错误)");
LogManager.Warning("[coordinate_system] 部分格式错误,将使用默认值");
}
else
{
config.CoordinateSystem = new CoordinateSystemConfig
{
Type = GetStringValueWithDefault(coordSys, "type", "AutoDetect", missingItems)
};
}
}
// 如果有缺失项,记录警告并设置标志
if (missingItems.Count > 0)
{
_hasMissingConfigItems = true;
_missingConfigItems = missingItems;
LogManager.Warning($"配置文件存在缺失项(共{missingItems.Count}项),已使用默认值填充");
LogManager.Warning($"缺失项: {string.Join(", ", missingItems)}");
}
return config;
}
/// <summary>
/// 创建空的配置对象(初始化所有嵌套对象)
/// </summary>
private SystemConfig CreateEmptyConfigObject()
{
return new SystemConfig
{
GridGeneration = new GridGenerationConfig(),
PathPlanning = new PathPlanningConfig(),
PathEditing = new PathEditingConfig(),
Visualization = new VisualizationConfig(),
Animation = new AnimationConfig(),
Logistics = new LogisticsConfig(),
CoordinateSystem = new CoordinateSystemConfig()
};
}
/// <summary>
/// 保存配置到文件
/// </summary>
public void SaveConfig(SystemConfig config)
{
SaveConfig(config, notifyChange: true);
}
/// <summary>
/// 保存配置到文件
/// </summary>
/// <param name="config">配置对象</param>
/// <param name="notifyChange">是否触发配置变更事件</param>
public void SaveConfig(SystemConfig config, bool notifyChange)
{
try
{
// 确保目录存在
Directory.CreateDirectory(ConfigDirectory);
var tomlContent = GenerateTomlFromConfig(config);
File.WriteAllText(ConfigFilePath, tomlContent);
_currentConfig = config;
LogManager.Info($"配置文件已保存: {ConfigFilePath}");
// 触发配置变更事件
if (notifyChange)
{
NotifyConfigurationChanged(ConfigCategory.All, isExternal: false);
}
}
catch (Exception ex)
{
LogManager.Error($"保存配置文件失败: {ex.Message}");
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
throw;
}
}
/// <summary>
/// 直接写入配置文件内容(不经过模板转换)
/// </summary>
private void WriteConfigFileDirect(string tomlContent)
{
try
{
// 确保目录存在
Directory.CreateDirectory(ConfigDirectory);
File.WriteAllText(ConfigFilePath, tomlContent);
LogManager.Info($"配置文件已创建: {ConfigFilePath}");
}
catch (Exception ex)
{
LogManager.Error($"写入配置文件失败: {ex.Message}");
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
throw;
}
}
/// <summary>
/// 从配置对象生成 TOML 字符串(使用模板格式)
/// </summary>
private string GenerateTomlFromConfig(SystemConfig config)
{
// 加载模板内容(缓存)
if (_cachedTemplateContent == null)
{
_cachedTemplateContent = ReadConfigTemplate();
}
// 解析模板
var syntax = Toml.Parse(_cachedTemplateContent);
var model = syntax.ToModel();
// 更新配置值到模型
ApplyConfigValuesToModel(model, config);
// 转换回 TOML 字符串
return Toml.FromModel(model);
}
/// <summary>
/// 将配置对象的值应用到 TOML 模型
/// </summary>
private void ApplyConfigValuesToModel(TomlTable model, SystemConfig config)
{
// 更新路径编辑配置
if (model.ContainsKey("path_editing"))
{
var pathEdit = model["path_editing"] as TomlTable;
if (pathEdit != null)
{
pathEdit["cell_size_meters"] = config.PathEditing.CellSizeMeters;
pathEdit["max_height_diff_meters"] = config.PathEditing.MaxHeightDiffMeters;
pathEdit["object_length_meters"] = config.PathEditing.ObjectLengthMeters;
pathEdit["object_width_meters"] = config.PathEditing.ObjectWidthMeters;
pathEdit["object_height_meters"] = config.PathEditing.ObjectHeightMeters;
pathEdit["safety_margin_meters"] = config.PathEditing.SafetyMarginMeters;
pathEdit["default_path_turn_radius"] = config.PathEditing.DefaultPathTurnRadiusMeters;
pathEdit["arc_sampling_step"] = config.PathEditing.ArcSamplingStepMeters;
}
}
// 更新可视化配置
if (model.ContainsKey("visualization"))
{
var visual = model["visualization"] as TomlTable;
if (visual != null)
{
visual["margin_ratio"] = config.Visualization.MarginRatio;
visual["passage_space_opacity"] = config.Visualization.PassageSpaceOpacity;
}
}
// 更新动画配置
if (model.ContainsKey("animation"))
{
var anim = model["animation"] as TomlTable;
if (anim != null)
{
anim["frame_rate"] = config.Animation.FrameRate;
anim["duration_seconds"] = config.Animation.DurationSeconds;
anim["detection_tolerance_meters"] = config.Animation.DetectionToleranceMeters;
anim["spatial_index_cell_size"] = config.Animation.SpatialIndexCellSizeMeters;
}
}
// 更新物流属性配置
if (model.ContainsKey("logistics"))
{
var logistics = model["logistics"] as TomlTable;
if (logistics != null)
{
logistics["traversable"] = config.Logistics.Traversable;
logistics["priority"] = config.Logistics.Priority;
logistics["height_limit_meters"] = config.Logistics.HeightLimitMeters;
logistics["speed_limit_meters_per_second"] = config.Logistics.SpeedLimitMetersPerSecond;
logistics["width_limit_meters"] = config.Logistics.WidthLimitMeters;
}
}
// 更新坐标系配置
if (model.ContainsKey("coordinate_system"))
{
var coordSys = model["coordinate_system"] as TomlTable;
if (coordSys != null && config.CoordinateSystem != null)
{
coordSys["type"] = config.CoordinateSystem.Type;
}
}
}
/// <summary>
/// 重新加载配置文件
/// </summary>
public void Reload()
{
ReloadInternal(isExternal: false);
}
/// <summary>
/// 内部重新加载方法
/// </summary>
/// <param name="isExternal">是否是外部修改触发的重载</param>
private void ReloadInternal(bool isExternal)
{
try
{
_currentConfig = LoadConfigFile();
LogManager.Info($"配置文件已重新加载{(isExternal ? "" : "")}");
// 触发配置变更事件
NotifyConfigurationChanged(ConfigCategory.All, isExternal);
}
catch (Exception ex)
{
LogManager.Error($"重新加载配置文件失败: {ex.Message}");
throw;
}
}
/// <summary>
/// 恢复为模板中的默认配置
/// </summary>
public void RestoreToDefaults()
{
LogManager.Info("开始恢复默认配置...");
var templateContent = ReadConfigTemplate();
LogManager.Info($"模板内容长度: {templateContent.Length}");
LogManager.Info($"模板内容前200字符: {templateContent.Substring(0, Math.Min(200, templateContent.Length))}");
WriteConfigFileDirect(templateContent);
var newConfig = ParseTomlToConfig(templateContent);
LogManager.Info($"解析后的配置 - CellSizeMeters: {newConfig.PathEditing.CellSizeMeters}");
LogManager.Info($"解析后的配置 - ObjectLengthMeters: {newConfig.PathEditing.ObjectLengthMeters}");
_currentConfig = newConfig;
// 清除配置兼容性警告(已恢复到完整配置)
ClearConfigCompatibilityWarning();
LogManager.Info("默认配置恢复完成");
// 触发配置变更事件
NotifyConfigurationChanged(ConfigCategory.All, isExternal: false);
}
/// <summary>
/// 触发配置变更事件
/// </summary>
/// <param name="category">变更的配置类别</param>
/// <param name="isExternal">是否是外部修改</param>
public void NotifyConfigurationChanged(ConfigCategory category, bool isExternal = false)
{
var args = new ConfigurationChangedEventArgs(category, isExternal);
try
{
// 触发总事件
ConfigurationChanged?.Invoke(this, args);
// 触发分类事件
CategoryConfigurationChanged?.Invoke(this,
new Tuple<ConfigCategory, ConfigurationChangedEventArgs>(category, args));
// 如果是 All触发各个分类事件
if (category == ConfigCategory.All)
{
for (int i = 1; i <= 7; i++)
{
CategoryConfigurationChanged?.Invoke(this,
new Tuple<ConfigCategory, ConfigurationChangedEventArgs>((ConfigCategory)i, args));
}
}
LogManager.Debug($"配置变更事件已触发: {category}");
}
catch (Exception ex)
{
LogManager.Error($"触发配置变更事件失败: {ex.Message}");
}
}
/// <summary>
/// 更新特定类别的配置并触发事件
/// </summary>
/// <param name="category">配置类别</param>
/// <param name="updateAction">更新操作</param>
public void UpdateCategoryConfig(ConfigCategory category, Action<SystemConfig> updateAction)
{
if (updateAction == null)
throw new ArgumentNullException(nameof(updateAction));
updateAction(_currentConfig);
SaveConfig(_currentConfig, notifyChange: false);
NotifyConfigurationChanged(category, isExternal: false);
}
/// <summary>
/// 资源释放
/// </summary>
public void Dispose()
{
if (!_isDisposed)
{
_fileWatcher?.Dispose();
_isDisposed = true;
LogManager.Info("ConfigManager 已释放");
}
}
// 辅助方法:从 TomlTable 获取必需值
private double GetRequiredDoubleValue(TomlTable table, string key)
{
if (!table.ContainsKey(key))
{
throw new InvalidOperationException($"配置项 '{key}' 不存在");
}
var value = table[key];
if (value is long longValue)
return (double)longValue;
if (value is double doubleValue)
return doubleValue;
throw new InvalidOperationException($"配置项 '{key}' 的类型错误,应为数值类型");
}
private int GetRequiredIntValue(TomlTable table, string key)
{
if (!table.ContainsKey(key))
{
throw new InvalidOperationException($"配置项 '{key}' 不存在");
}
var value = table[key];
if (value is long longValue)
return (int)longValue;
throw new InvalidOperationException($"配置项 '{key}' 的类型错误,应为整数类型");
}
private bool GetRequiredBoolValue(TomlTable table, string key)
{
if (!table.ContainsKey(key))
{
throw new InvalidOperationException($"配置项 '{key}' 不存在");
}
var value = table[key];
if (value is bool boolValue)
return boolValue;
throw new InvalidOperationException($"配置项 '{key}' 的类型错误,应为布尔类型");
}
/// <summary>
/// 获取字符串配置值(可选,有默认值)
/// </summary>
private string GetStringValue(TomlTable table, string key, string defaultValue)
{
if (!table.ContainsKey(key))
{
return defaultValue;
}
return table[key]?.ToString() ?? defaultValue;
}
/// <summary>
/// 获取必需的字符串配置值
/// </summary>
private string GetRequiredStringValue(TomlTable table, string key)
{
if (!table.ContainsKey(key))
{
throw new InvalidOperationException($"配置项 '{key}' 不存在");
}
var value = table[key];
if (value == null)
{
throw new InvalidOperationException($"配置项 '{key}' 的值为 null");
}
var strValue = value.ToString();
if (string.IsNullOrWhiteSpace(strValue))
{
throw new InvalidOperationException($"配置项 '{key}' 不能为空");
}
return strValue;
}
#region
/// <summary>
/// 获取 double 配置值(带默认值,不抛出异常)
/// </summary>
private double GetDoubleValueWithDefault(TomlTable table, string key, double defaultValue, List<string> missingItems)
{
if (!table.ContainsKey(key))
{
missingItems.Add($"{key}");
LogManager.Debug($"配置项 '{key}' 不存在,使用默认值: {defaultValue}");
return defaultValue;
}
var value = table[key];
if (value is long longValue)
return (double)longValue;
if (value is double doubleValue)
return doubleValue;
missingItems.Add($"{key} (类型错误)");
LogManager.Warning($"配置项 '{key}' 类型错误,使用默认值: {defaultValue}");
return defaultValue;
}
/// <summary>
/// 获取 float 配置值(带默认值,不抛出异常)
/// </summary>
private float GetFloatValueWithDefault(TomlTable table, string key, float defaultValue, List<string> missingItems)
{
if (!table.ContainsKey(key))
{
missingItems.Add($"{key}");
LogManager.Debug($"配置项 '{key}' 不存在,使用默认值: {defaultValue}");
return defaultValue;
}
var value = table[key];
if (value is long longValue)
return (float)longValue;
if (value is double doubleValue)
return (float)doubleValue;
missingItems.Add($"{key} (类型错误)");
LogManager.Warning($"配置项 '{key}' 类型错误,使用默认值: {defaultValue}");
return defaultValue;
}
/// <summary>
/// 获取 int 配置值(带默认值,不抛出异常)
/// </summary>
private int GetIntValueWithDefault(TomlTable table, string key, int defaultValue, List<string> missingItems)
{
if (!table.ContainsKey(key))
{
missingItems.Add($"{key}");
LogManager.Debug($"配置项 '{key}' 不存在,使用默认值: {defaultValue}");
return defaultValue;
}
var value = table[key];
if (value is long longValue)
return (int)longValue;
missingItems.Add($"{key} (类型错误)");
LogManager.Warning($"配置项 '{key}' 类型错误,使用默认值: {defaultValue}");
return defaultValue;
}
/// <summary>
/// 获取 bool 配置值(带默认值,不抛出异常)
/// </summary>
private bool GetBoolValueWithDefault(TomlTable table, string key, bool defaultValue, List<string> missingItems)
{
if (!table.ContainsKey(key))
{
missingItems.Add($"{key}");
LogManager.Debug($"配置项 '{key}' 不存在,使用默认值: {defaultValue}");
return defaultValue;
}
var value = table[key];
if (value is bool boolValue)
return boolValue;
missingItems.Add($"{key} (类型错误)");
LogManager.Warning($"配置项 '{key}' 类型错误,使用默认值: {defaultValue}");
return defaultValue;
}
/// <summary>
/// 获取 string 配置值(带默认值,不抛出异常)
/// </summary>
private string GetStringValueWithDefault(TomlTable table, string key, string defaultValue, List<string> missingItems)
{
if (!table.ContainsKey(key))
{
missingItems.Add($"{key}");
LogManager.Debug($"配置项 '{key}' 不存在,使用默认值: {defaultValue}");
return defaultValue;
}
var value = table[key];
if (value == null)
{
missingItems.Add($"{key} (null值)");
LogManager.Warning($"配置项 '{key}' 为 null使用默认值: {defaultValue}");
return defaultValue;
}
var strValue = value.ToString();
if (string.IsNullOrWhiteSpace(strValue))
{
missingItems.Add($"{key} (空值)");
LogManager.Warning($"配置项 '{key}' 为空,使用默认值: {defaultValue}");
return defaultValue;
}
return strValue;
}
#endregion
}
}