【Hi.Ltd 专题】第9期:Interop 配置互操作(JSON/INI/XML/YAML/注册表/扫码)

Hi.Ltd 专题第 9 期 |模块:InteropHi.Ltd.Interop.* + Hi.Ltd.Interface.I*)|NuGet:Hi.Ltd 2026.7.11.1437

目标框架:net462 / net481 / net6.0 / net8.0

场景:设备 INI、配方 JSON/YAML、XML 点表、CSV 班报、注册表授权项、扫码枪 Hook。

第8期:Managements 插件、单例与服务定位


本期目标

  1. JsonHelper / IniHelper / YamlHelper / XmlUtils / TomlUtils / CsvUtils 做配置往返
  2. IniBase 段键 API 与 XmlBase 两层/三层点表 API
  3. RegistryFacade 把对象序列化进注册表树(HKey
  4. ScannerBase/IScanner 接扫码枪全局钩子
  5. 分清 Create/Instance(path) 单例与文件路径参数

适用范围

场景 推荐类型
设备 IP/端口配方 IniHelperJsonHelper
MES 风格 YAML 配置 YamlHelper + GetValueByPath
老点表 XML Xml/XmlBase ThreeLayer
产量 CSV 导出导入 CsvUtils
授权码写 HKLM/HKCU RegistryFacade
USB 扫码枪当键盘 ScannerBase

不该用 / 慎用

场景 说明
指望 System.Text.Json 自动认本包特性 需走 JsonHelper 或自定义合同
扫码 Hook 与快捷键冲突未测 产线键盘布局要回归
注册表写 HKLM 无权限 需提权安装器;本包 无 App 提权类型

安装引用

csharp 复制代码
using Hi.Ltd.Interop;
using Hi.Ltd.Interface;
using Hi.Ltd.Enumerations; // HKey
using Hi.Ltd.Attributes;   // JsonProperty / YamlMember

互操作性(DLL)

领域 门面/工具 底层 接口
JSON JsonHelper / JsonSerializer JsonBase (Https 另有 IHttpJsonSerializer
INI IniHelper / Ini IniBase IIni
YAML YamlHelper / Yaml YamlBase IYaml
XML XmlUtils / Xml XmlBase IXml
TOML TomlUtils TomlBase IToml
CSV CsvUtils CsvBase ICsv
XLIFF XliffUtils XliffBase IXliff
注册表 RegistryHelper / RegistryFacade RegistryBase IRegistry
扫码 ScannerUtils ScannerBase / ScannerHookToUnicode IScanner
通用 Serializer / PropertyObjectSerialization

JSON(JsonHelper)

XML:支持类/结构体/列表/字典;JsonIgnore/JsonProperty/CamelCase;与 Newtonsoft 常用用法对齐。

csharp 复制代码
public sealed class DeviceConfig
{
    [Hi.Ltd.Attributes.JsonProperty("ip")]
    public string Ip { get; set; }
    public int Port { get; set; }
}

var cfg = new DeviceConfig { Ip = "192.168.1.10", Port = 502 };

// 序列化为字符串(可显式传 camelCase / 输出 null 策略)
string json = JsonHelper.Create.SerializeToJsonString(cfg, useCamelCase: true, ignoreNull: true);

DeviceConfig back = JsonHelper.Create.DeserializeFromString<DeviceConfig>(json);

// 落盘
JsonHelper.Create.Serialize(@"D:\cfg\device.json", cfg);
var fromFile = JsonHelper.Create.Deserialize<DeviceConfig>(@"D:\cfg\device.json");

// 带路径单例
var helper = JsonHelper.Instance(@"D:\cfg\device.json");
string raw = JsonHelper.Create.ReadToJson(@"D:\cfg\device.json");

注1:此实现只是为了避免引入第三方库,保持基础库的纯净,有特殊需求建议使用 Newtonsoft 类库


INI(IniHelper / IniBase)

csharp 复制代码
// 对象 ↔ INI 文件
IniHelper.Create.Serialize(@"D:\cfg\device.ini", cfg);
var cfg2 = IniHelper.Create.Deserialize<DeviceConfig>(@"D:\cfg\device.ini");

// 扁平加速(不支持嵌套)
IniHelper.Create.FastSerialize(@"D:\cfg\flat.ini", cfg, sectionName: "Device");
var flat = IniHelper.Create.FastDeserialize<DeviceConfig>(@"D:\cfg\flat.ini", "Device");

注:此序列化操作只针对简单的数据类型,复杂的,比如列表,数组,字典等请改用其它的文件类型

段键级(IniBase / IIni):

csharp 复制代码
IIni ini = IniHelper.Instance(@"D:\cfg\comm.ini");
ini.WriteValue("PLC", "Ip", "192.168.1.10");
string ip = ini.GetStringValue("PLC", "Ip", defaultValue: "127.0.0.1");
string[] sections = ini.GetAllSectionNames();
var items = ini.GetAllItems("PLC");
ini.DeleteKey("PLC", "Unused");
ini.EmptySection("Temp");

YAML(YamlHelper)

csharp 复制代码
string yaml = YamlHelper.Create.SerializeToYamlString(cfg);
var rYaml = YamlHelper.Create.SerializeToYamlStringResult(cfg); // Result 版

YamlHelper.Create.Serialize(@"D:\cfg\device.yaml", cfg);
var cfg3 = YamlHelper.Create.Deserialize<DeviceConfig>(@"D:\cfg\device.yaml");

if (YamlHelper.Create.TryDeserialize<DeviceConfig>(@"D:\cfg\device.yaml", out var cfg4))
{ /* ok */ }

var dict = YamlHelper.Create.ReadToDictionary(@"D:\cfg\device.yaml");
int port = YamlHelper.GetValueByPath(dict, "server.port", defaultValue: 502);
var portR = YamlHelper.GetValueByPathResult<int>(dict, "server.port");

// 多文档 ---
var docs = YamlHelper.ParseDocuments(yamlText);
var docsR = YamlHelper.ParseDocumentsResult(yamlText);

键名:YamlMember.Alias 或 camelCase(GetYamlKeyForProperty)。


XML 点表(XmlBase / XmlUtils)

对象序列化:

csharp 复制代码
XmlUtils.Instance.Serialize(@"D:\points\axis.xml", cfg);
var x = XmlUtils.Instance.Deserialize<DeviceConfig>(@"D:\points\axis.xml");
var named = XmlUtils.GetInstance(@"D:\points\axis.xml", root: "Root");

层级点表(XmlBase/IXml):CreateFileAdd/AddSingleAddThreeLayer*Alter*Write*Read*/ReadSingle/ReadThreeLayer*Delete*

csharp 复制代码
// 示意:两层/三层读写 ------ 具体参数顺序以 IntelliSense/XML 为准
// CreateFile(path, rootName)
// WriteThreeLayerSingle(path, root, child, grand, key, value)
// ReadThreeLayerSingle(..., out value)

CSV / TOML / XLIFF

csharp 复制代码
// CSV:列表往返,可指定 hasHeader / separator
string csv = CsvUtils.Create.SerializeToCsvString(rows, hasHeader: true, separator: ',');
CsvUtils.Create.Serialize(@"D:\report\shift.csv", rows, true, ',');
var list = CsvUtils.Create.Deserialize<RowDto>(@"D:\report\shift.csv", true, ',');

// TOML
string toml = TomlUtils.Create.SerializeToTomlString(cfg);
TomlUtils.Create.Serialize(@"D:\cfg\app.toml", cfg);
var t = TomlUtils.Create.DeserializeFromString<DeviceConfig>(toml);
var dictT = TomlUtils.Create.ParseToDictionary(toml);

XLIFF:本地化交换,见 XliffUtils/IXliff(与 LocateFactory 场景相邻)。


注册表(RegistryFacade)

命名刻意避开 Microsoft.Win32.Registry

csharp 复制代码
using Hi.Ltd.Enumerations;

RegistryFacade.Serialize(
    HKey.CURRENT_USER,
    @"Software\HiLtd\Line1",
    cfg,
    name: null);

var back = RegistryFacade.Deserialize<DeviceConfig>(
    HKey.CURRENT_USER,
    @"Software\HiLtd\Line1",
    name: null);

// 扁平
RegistryFacade.FastSerialize(HKey.LOCAL_MACHINE, @"Software\HiLtd\License", license, null);

注:同样基于跨平台的需求,此部分后续会移植到Hi.Ltd.Win32类库。


扫码枪(ScannerBase)

csharp 复制代码
using Hi.Ltd.Interop;
using Hi.Ltd.Interface;

public sealed class LineScanner : ScannerBase
{
}

var scanner = new LineScanner();
scanner.OnScannerCode += code =>
{
    $"扫码入站: {code}".Info();
    // 工单号入队
};
scanner.Start();
// scanner.StartInActive(heartbeatMs);
// scanner.Stop(); scanner.Dispose();

ScannerHookToUnicode.ToUnicode 等处理钩子键码与修饰键。


完整示例:启动加载 INI,失败回退 JSON

csharp 复制代码
using System.IO;
using Hi.Ltd.Interop;

public static class ConfigLoader
{
    public static DeviceConfig Load(string iniPath, string jsonFallback)
    {
        try
        {
            if (File.Exists(iniPath))
                return IniHelper.Create.Deserialize<DeviceConfig>(iniPath);
        }
        catch (System.Exception ex)
        {
            $"INI 加载失败,回退 JSON: {ex.Message}".Warn();
        }

        string json = File.ReadAllText(jsonFallback);
        return JsonHelper.Create.DeserializeFromString<DeviceConfig>(json);
    }

    public static void SaveBoth(DeviceConfig cfg, string iniPath, string jsonPath)
    {
        IniHelper.Create.Serialize(iniPath, cfg);
        JsonHelper.Create.Serialize(jsonPath, cfg);
    }
}

若某 API 返回 Result,改为看 Successed,勿盲目 catch。


可能出现的问题(现场坑)

  1. Utilities FromJson 返回 T vs Interop Helper------错误模型可能不同。
  2. INI 中文乱码 / 节名大小写
  3. 注册表权限(HKLM);本包无 App 提权。
  4. 扫码 Hook 与输入法/快捷键冲突
  5. YAML 多文档ParseDocuments*
  6. FastSerialize 丢嵌套 ------嵌套对象用完整 Serialize
  7. JsonHelper.Create 无路径------落盘必须传 path。

异常点与应对

现象 应对
反序列化字段丢失 JsonProperty/YamlMember 别名
INI 乱码 统一系统 ANSI/UTF-8 策略;关键写回
注册表写失败 ACL;正确 HKey
扫码丢字符 ScannerHookToUnicode;调钩子与焦点
XML 节点不存在 Read* 可能得 null------先 CreateFile/Write

常见问题

Q: Https 泛型 JSON 用哪套?

A: IHttpJsonSerializer,默认即 JsonHelper 实现。


下篇预告

第10期:Data(ASCII / Dongle / PagedList / Native / 拼音档)

相关推荐
Regentsoft丽晶软件3 小时前
即时零售退货的库存归属、质检标准和退款时效,系统如何做到自动闭环
大数据·经验分享·数据库架构
2601_965384263 小时前
口腔黏膜清洁的工程化路径:从表面形貌表征到清洁策略匹配
经验分享·笔记
2401_850122046 小时前
航空、轨交、汽车线束防护有什么不同?三大行业的共性、差异与选型逻辑
经验分享·笔记·科技
tang_04277 小时前
【Hi.Ltd 专题】第7期:Threading 采集线程、锁与 LRU 缓存
经验分享·c#·hi.ltd系列
A_nanda7 小时前
C# 界面卡顿:从定位到根治
c#
人效思维笔记7 小时前
阿米巴推行前,经营者要先做好哪些准备?
经验分享·笔记·阿米巴·阿米巴经营·中国式阿米巴
2501_930707788 小时前
使用C#代码为新创建的 Word 文档创建目录
c#·word
hongyangcao9 小时前
12.8万科技岗位被“重组“,预算流向了算力
人工智能·经验分享·ai编程
czhc11400756639 小时前
同一个数,两把尺子:六组“看着一样、其实不一样“
c#