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

Hi.Ltd 专题第 9 期 |模块:Interop (Hi.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/端口配方 IniHelper 或 JsonHelper
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):CreateFile、Add/AddSingle、AddThreeLayer*、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 / 拼音档)

相关推荐
总线通信小百科9 小时前
车载以太网模块、交换机与媒体转换器:三类设备怎么选?
经验分享·车载以太网
2601_9672127213 小时前
安全型轨道式插座合规资质核查与工程选型技术要点
大数据·经验分享·安全
一只代码猿15 小时前
Screen Studio 免费邪修用法:剪视频完全无痛(附提示词)
经验分享
蒋胜山16 小时前
VBScript007-Excel的99乘法表
经验分享·batch
德思特16 小时前
实操指南|从“能驻网“到“能上网“:手机入网与公网业务实验室测试分享
经验分享·无线通信
览讯冷却17 小时前
冷却塔噪声的健康危害与法规要求的技术梳理
经验分享·笔记·科技·其他·百度·制造·业界资讯
学页技术极客18 小时前
「Skill市场」会重演「App Store」的故事吗
经验分享
恒锐丰科技林技术员18 小时前
EG2304L 高压半桥驱动芯片:中小功率电力电子方案优选器件
经验分享·嵌入式硬件·硬件工程
哎写bug的程序员20 小时前
关于github
经验分享
lazy H21 小时前
【计算机网络】第 12 篇:IPv6 详解——地址格式、地址类型与双栈网络
网络·经验分享·后端·学习·计算机网络·408