[XP.Hardware.Detector] DetectorWorkMode 枚举扩展为 9 个预设模式;新增 DetectorPreset 模型类、PresetLoader(JSON 配置文件加载器)。

This commit is contained in:
QI Mingxuan
2026-07-10 16:55:10 +08:00
parent 0bdd472e72
commit 9315bcdbef
7 changed files with 169 additions and 7 deletions
+17 -3
View File
@@ -89,13 +89,28 @@ namespace XP.Hardware.Detector.Config
/// <summary>
/// 获取指定工作模式的完整参数预设 | Get full parameter preset for the given work mode
/// Custom 模式返回 null(由用户自由设定)| Returns null for Custom mode (user sets manually)
/// 子类应重写以提供设备型号专属的参数组合 | Subclass should override for model-specific parameter combinations
/// 优先从 JSON 配置文件加载,加载失败时回退到代码默认值
/// Loads from JSON config file first, falls back to code defaults on failure
/// </summary>
/// <param name="mode">工作模式 | Work mode</param>
/// <returns>参数预设,Custom 时返回 null | Parameter preset, null for Custom</returns>
public virtual DetectorPreset GetPreset(DetectorWorkMode mode)
{
// 基类提供通用默认值(基于 1×1/2×2 两种 Binning | Base class provides generic defaults
if (mode == DetectorWorkMode.Custom) return null;
// 优先从 JSON 配置文件加载 | Try JSON config file first
var fromJson = PresetLoader.TryLoadFromJson(Type, mode);
if (fromJson != null) return fromJson;
// 回退到代码默认值 | Fallback to code defaults
return GetDefaultPreset(mode);
}
/// <summary>
/// 代码内置的默认预设参数(JSON 加载失败时使用)| Built-in default preset parameters (used when JSON fails)
/// </summary>
protected virtual DetectorPreset GetDefaultPreset(DetectorWorkMode mode)
{
return mode switch
{
DetectorWorkMode.HighQuality => new DetectorPreset(mode, binningIndex: 0, frameRate: 1m, avgFrames: 8, pga: 4),
@@ -106,7 +121,6 @@ namespace XP.Hardware.Detector.Config
DetectorWorkMode.HighDynamicFullRes=> new DetectorPreset(mode, binningIndex: 0, frameRate: 3m, avgFrames: 4, pga: 6),
DetectorWorkMode.HighDynamic => new DetectorPreset(mode, binningIndex: 1, frameRate: 15m, avgFrames: 2, pga: 6),
DetectorWorkMode.LowDosage => new DetectorPreset(mode, binningIndex: 0, frameRate: 3m, avgFrames: 1, pga: 2),
DetectorWorkMode.Custom => null,
_ => null
};
}
@@ -121,9 +121,9 @@ namespace XP.Hardware.Detector.Config
};
/// <summary>
/// iRay 工作模式参数预设 | iRay work mode parameter presets
/// iRay 工作模式参数预设(代码默认值)| iRay work mode parameter presets (code defaults)
/// </summary>
public override DetectorPreset GetPreset(DetectorWorkMode mode)
protected override DetectorPreset GetDefaultPreset(DetectorWorkMode mode)
{
return mode switch
{
+119
View File
@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using XP.Hardware.Detector.Abstractions.Enums;
namespace XP.Hardware.Detector.Config
{
/// <summary>
/// 预设加载器 | Preset loader
/// 从 JSON 配置文件加载预设参数,覆盖代码默认值
/// Loads preset parameters from JSON config file, overriding code defaults
/// </summary>
public static class PresetLoader
{
private static Dictionary<string, Dictionary<string, PresetJson>> _cache = new();
private static readonly object _lock = new();
/// <summary>
/// 尝试从 JSON 文件加载指定模式的预设 | Try to load preset for given mode from JSON file
/// </summary>
/// <param name="detectorType">探测器类型 | Detector type</param>
/// <param name="mode">工作模式 | Work mode</param>
/// <returns>预设参数,加载失败或无此模式时返回 null | Preset, or null if failed/not found</returns>
public static DetectorPreset TryLoadFromJson(DetectorType detectorType, DetectorWorkMode mode)
{
if (mode == DetectorWorkMode.Custom) return null;
var modeName = mode.ToString();
var presets = LoadPresetsFile(detectorType);
if (presets == null || !presets.ContainsKey(modeName)) return null;
var json = presets[modeName];
return new DetectorPreset(mode, json.BinningIndex, json.FrameRate, json.AvgFrames, json.Pga);
}
/// <summary>
/// 加载探测器对应的预设文件(带缓存)| Load preset file for detector type (with cache)
/// </summary>
private static Dictionary<string, PresetJson> LoadPresetsFile(DetectorType detectorType)
{
var fileName = GetPresetFileName(detectorType);
if (string.IsNullOrEmpty(fileName)) return null;
lock (_lock)
{
if (_cache.ContainsKey(fileName)) return _cache[fileName];
try
{
// 查找 JSON 文件路径:优先 exe 同级目录,其次 Config/Presets 子目录
// Search path: prefer exe directory, then Config/Presets subdirectory
var basePath = AppDomain.CurrentDomain.BaseDirectory;
var filePath = Path.Combine(basePath, fileName);
if (!File.Exists(filePath))
{
filePath = Path.Combine(basePath, "Config", "Presets", fileName);
}
if (!File.Exists(filePath))
{
_cache[fileName] = null;
return null;
}
var jsonText = File.ReadAllText(filePath);
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
ReadCommentHandling = JsonCommentHandling.Skip
};
var dict = JsonSerializer.Deserialize<Dictionary<string, PresetJson>>(jsonText, options);
_cache[fileName] = dict;
return dict;
}
catch
{
// JSON 解析失败时回退到代码默认值 | Fallback to code defaults on parse failure
_cache[fileName] = null;
return null;
}
}
}
/// <summary>
/// 根据探测器类型确定 JSON 文件名 | Determine JSON file name by detector type
/// </summary>
private static string GetPresetFileName(DetectorType detectorType)
{
return detectorType switch
{
DetectorType.Varex => "VarexPresets.json",
DetectorType.IRay => "IRayPresets.json",
_ => null
};
}
/// <summary>
/// 清除缓存(测试用或配置文件更新后调用)| Clear cache (for testing or after config file update)
/// </summary>
public static void ClearCache()
{
lock (_lock)
{
_cache.Clear();
}
}
/// <summary>
/// JSON 反序列化模型 | JSON deserialization model
/// </summary>
private class PresetJson
{
public int BinningIndex { get; set; }
public decimal FrameRate { get; set; }
public int AvgFrames { get; set; }
public int Pga { get; set; }
}
}
}
@@ -0,0 +1,10 @@
{
"HighQuality": { "BinningIndex": 0, "FrameRate": 1, "AvgFrames": 8, "Pga": 4 },
"MediumQuality": { "BinningIndex": 0, "FrameRate": 10, "AvgFrames": 4, "Pga": 4 },
"RealTime": { "BinningIndex": 1, "FrameRate": 30, "AvgFrames": 1, "Pga": 4 },
"HighSpeed": { "BinningIndex": 2, "FrameRate": 45, "AvgFrames": 1, "Pga": 4 },
"RealTimeFullRes": { "BinningIndex": 0, "FrameRate": 15, "AvgFrames": 1, "Pga": 4 },
"HighDynamicFullRes": { "BinningIndex": 0, "FrameRate": 3, "AvgFrames": 4, "Pga": 7 },
"HighDynamic": { "BinningIndex": 1, "FrameRate": 15, "AvgFrames": 2, "Pga": 7 },
"LowDosage": { "BinningIndex": 0, "FrameRate": 3, "AvgFrames": 1, "Pga": 1 }
}
@@ -0,0 +1,10 @@
{
"HighQuality": { "BinningIndex": 0, "FrameRate": 1, "AvgFrames": 8, "Pga": 4 },
"MediumQuality": { "BinningIndex": 0, "FrameRate": 10, "AvgFrames": 4, "Pga": 4 },
"RealTime": { "BinningIndex": 1, "FrameRate": 30, "AvgFrames": 1, "Pga": 4 },
"HighSpeed": { "BinningIndex": 2, "FrameRate": 60, "AvgFrames": 1, "Pga": 4 },
"RealTimeFullRes": { "BinningIndex": 0, "FrameRate": 15, "AvgFrames": 1, "Pga": 4 },
"HighDynamicFullRes": { "BinningIndex": 0, "FrameRate": 3, "AvgFrames": 4, "Pga": 6 },
"HighDynamic": { "BinningIndex": 1, "FrameRate": 15, "AvgFrames": 2, "Pga": 6 },
"LowDosage": { "BinningIndex": 0, "FrameRate": 3, "AvgFrames": 1, "Pga": 2 }
}
@@ -70,9 +70,9 @@ namespace XP.Hardware.Detector.Config
};
/// <summary>
/// Varex 4343N 工作模式参数预设 | Varex 4343N work mode parameter presets
/// Varex 4343N 工作模式参数预设(代码默认值)| Varex 4343N work mode parameter presets (code defaults)
/// </summary>
public override DetectorPreset GetPreset(DetectorWorkMode mode)
protected override DetectorPreset GetDefaultPreset(DetectorWorkMode mode)
{
return mode switch
{
@@ -27,6 +27,15 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<!-- 预设配置文件复制到输出目录(可选覆盖代码默认值)| Preset config files copied to output (optional override for code defaults) -->
<Content Include="Config\Presets\VarexPresets.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Config\Presets\IRayPresets.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Compile Update="Resources\Resources.Designer.cs">
<DesignTime>True</DesignTime>