DataKit.Parser 1.0.1

dotnet add package DataKit.Parser --version 1.0.1
                    
NuGet\Install-Package DataKit.Parser -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DataKit.Parser" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DataKit.Parser" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="DataKit.Parser" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DataKit.Parser --version 1.0.1
                    
#r "nuget: DataKit.Parser, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DataKit.Parser@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DataKit.Parser&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=DataKit.Parser&version=1.0.1
                    
Install as a Cake Tool

DataKit 数据解析类库 · 中文操作文档

DataKit 是一个 零依赖、面向 .NET 8/9 的轻量级 C# 类库,用来读取并查询 JSON / XML / TXT / CSV / INI 五种常见数据格式。它的核心设计理念是:

无论底层数据是哪种格式,解析后都会归一化成同一棵「数据树(DataNode)」,你用完全相同的一套 API、同一套路径语法就能取任意格式里的值。

  • 目标框架:.NET 8 与 .NET 9(多目标 net8.0;net9.0)
  • 依赖:System.Text.Json、System.Linq.XDocument、System.Text.Encoding.CodePages,均为 .NET 自带,无需额外安装 NuGet 包
  • 编译产物:DataKit.dll(对应 NuGet 包内 lib/net8.0/ 与 lib/net9.0/)

目录

  1. 安装与引用
  2. 核心概念
  3. 解析数据:入口 API
  4. 路径语法
  5. 取值方法
  6. 强类型反序列化
  7. 各格式约定
  8. 编码与乱码处理
  9. 重新序列化 / 导出
  10. 错误处理
  11. 完整示例
  12. 常见问题 FAQ

1. 安装与引用

方式零:通过 NuGet 安装(推荐,最省事)

在你的项目目录下执行:

dotnet add package DataKit.Parser

或在 .csproj 中直接引用:

<ItemGroup>
  <PackageReference Include="DataKit.Parser" Version="1.0.0" />
</ItemGroup>

本库已发布到 NuGet,包名为 DataKit.Parser(注意:NuGet 包名与程序集/命名空间名 DataKit 不同)。在代码里引入命名空间时仍用 using DataKit;。

方式一:项目引用(便于本地调试类库源码)

在你的 C# 项目(.csproj)里添加:

<ItemGroup>
  <ProjectReference Include="..\DataKit\DataKit.csproj" />
</ItemGroup>

或在项目目录下执行:

dotnet add reference ..\DataKit\DataKit.csproj

方式二:DLL 引用

  1. 先生成类库:dotnet build -c Release
  2. 在 DataKit/bin/Release/net8.0/ 或 DataKit/bin/Release/net9.0/ 中找到 DataKit.dll
  3. 在你的项目里「添加引用 → 浏览 → 选择该 DLL」

注意:你的程序目标框架必须是 .NET 8 或 .NET 9(net8.0 / net9.0)。如果是老旧的 .NET Framework 4.x 项目,需要把类库的 TargetFramework 改为 netstandard2.0 后重新编译(功能会有小幅差异)。

在代码里引入命名空间

using DataKit;        // DataParser / DataDocument / DataNode / TextFixer

2. 核心概念

库里只有三个你真正要打交道的核心类型:

类型 作用
DataParser 静态入口。把文本/文件/流解析成 DataDocument。
DataDocument 一份解析后的文档。包着根节点,提供所有「按路径取值」的便捷方法。
DataNode 数据树上的一个节点(可以是一个值、一个对象,或一个数组)。

所有解析器(JSON/XML/TXT/CSV/INI)产出的都是 DataNode 树,因此你查询数据的方式与原始格式无关。

节点类型 NodeKind:

  • Value —— 标量(字符串、数字、布尔、null)
  • Object —— 有名字的成员集合(如 JSON 对象、XML 元素)
  • Array —— 有序的项集合(如 JSON 数组、CSV 多行)

3. 解析数据:入口 API

所有解析入口都在 DataParser 上,均为静态方法。

// 自动识别格式:以 { 或 [ 开头 → JSON;以 < 开头 → XML;其余 → 纯文本
DataDocument doc = DataParser.Parse(content);

// 显式指定格式
var d1 = DataParser.ParseJson(jsonText);   // JSON
var d2 = DataParser.ParseXml(xmlText);     // XML
var d3 = DataParser.ParseText(plainText);  // 纯文本(见第 7.4 节约定)
var d4 = DataParser.ParseCsv(csvText);     // CSV(首行作为表头)
var d5 = DataParser.ParseIni(iniText);     // INI

// 解析文件(按扩展名判断格式)
var d6 = DataParser.ParseFile("config.json");

// 解析流(适合网络响应、嵌入资源等)
using var stream = File.OpenRead("data.xml");
var d7 = DataParser.ParseStream(stream);

解析文件时的格式判定

ParseFile(path) 按文件扩展名选择解析器:

扩展名 解析为
.json JSON
.xml XML
.txt 纯文本
.csv CSV
.ini INI
其它 自动识别(同 Parse)

ParseCsv 指定分隔符

// 默认逗号;分号分隔的 CSV 可以这样:
var d = DataParser.ParseCsv(csvText, delimiter: ';');

4. 路径语法

路径是取数据的核心。所有 Get* / TryGet* 方法都接收一个 path 字符串。

4.1 点号访问(对象成员)

doc.Get("user.address.city");
doc.Get("server.host");

4.2 方括号访问(数组索引)

doc.Get("items[0].name");     // 第一个 item 的 name
doc.Get("list[2]");           // 第三个元素

也支持用点 + 数字(等价写法):

doc.Get("items.0.name");      // 等同 items[0].name

4.3 谓词过滤(按值筛选数组元素)⭐

这是本库最方便的特性之一:直接在路径里筛选数组中满足条件的一项。

语法:数组路径[键=值] 或 数组路径[键==值](两种等号都支持)。

条件键不限于 id:id 只是最常见的例子,方括号里的「键」可以是该数组项的任意标量成员。JSON 用普通成员名(如 name、team、role),XML 用带 @ 前缀的属性名(如 @id、@type)。用哪个属性当条件,由你决定。

// 取 match 数组中第一个 id 等于 5 的那一项
doc.Get("match[id=5]");
doc.GetString("match[id=5].name");   // 该项的 name 字段
doc.GetInt("match[id=5].id");        // 该项的 id 字段(=5)

// 换成任意属性同样可以:用 team 字段当条件
doc.GetString("match[team=\"Greuther Fürth\"].score");

// XML:用 @属性 当条件(注意前缀 @)
doc.GetString("person[@id=7].name");
doc.GetString("person[@type=\"guest\"].name");
  • 数字按数值比较(id=5 会匹配数值 5,而非字符串 "5")。
  • 字符串值需要加引号:
doc.GetString("users[role=\"admin\"].u");    // 双引号
doc.GetString("users[role='guest'].u");      // 单引号均可
  • 谓词只返回第一个命中项。找不到则该路径解析失败。

当前 match[id=5] 只会返回第一条 id=5。若你的数据里 id=5 有多条、需要「返回全部」,可联系维护者增加 match[id=5]* 之类的「返回全部」语法。

4.4 路径语法小结

写法 含义
a.b.c 逐层访问对象成员
a[0] / a.0 数组第 1 项(索引从 0 开始)
a[id=5] 数组里 id 等于 5 的第一项(id 可换成任意标量成员,如 a[team="X"]、a[@type="guest"])
a[role="admin"] 数组里 role 等于 "admin" 的第一项

5. 取值方法

拿到路径后,用 DataDocument 上的一系列方法取出目标类型。

5.1 带异常的取值(推荐在「确定存在」时用)

string?  s  = doc.GetString("user.name");
bool     b  = doc.GetBool("user.active");
int      i  = doc.GetInt("user.age");
long     l  = doc.GetLong("user.bigId");
double   d  = doc.GetDouble("user.score");
decimal  m  = doc.GetDecimal("user.price");
DateTime dt = doc.GetDateTime("user.createdAt");

// 拿节点本身(进一步遍历/取子字段)
DataNode node = doc.Get("match[id=5]");

这些 Get* 方法在路径解析不到时会抛出 DataKitException。取值类型不匹配时(比如对一个非数字字符串调 GetInt)也会抛异常。

5.2 带默认值的取值(字符串专用)

// 取不到或为空时返回默认值,不抛异常
string s = doc.GetString("user.nickname", "匿名用户");

5.3 安全取值(不确定是否存在时用)

// 取节点
if (doc.TryGet("a.b.c", out var node))
{
    var v = node.AsString();
}

// 直接取某个类型的值
if (doc.TryGetValue<int>("user.age", out var age))
{
    Console.WriteLine(age);
}

TryGet / TryGetValue 在路径解析不到时返回 false,不会抛异常。

5.4 在节点上取值

你也可以通过 DataNode 自身的方法来取:

DataNode user = doc.Get("user");
string name = user.GetString("name");      // 相对当前节点的路径
string name2 = user["name"].AsString();    // 直接索引器
int    age  = user["age"].AsInt();

// 遍历数组
DataNode items = doc.Get("items");
foreach (var item in items.Items)
{
    Console.WriteLine(item.GetString("tag"));
}

// 遍历对象成员
foreach (var kv in doc.Get("user").Members)
{
    Console.WriteLine($"{kv.Key} = {kv.Value.AsString()}");
}

索引器说明:

node["key"]     // 对象按名字取;数组按数字字符串取
node[0]         // 数组按索引取(越界抛异常)

5.5 布尔解析的宽容规则

AsBool() / GetBool() 接受:true/false、1/0、yes/no、on/off、是/否(不区分大小写)。例如 INI/TXT 里写的 enabled=yes 也能正确解析成 true。


6. 强类型反序列化

如果某个子树对应你定义好的 C# 类,可直接反序列化成对象(底层用 System.Text.Json):

public class User
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
    public bool Active { get; set; }
}

// 把 user 子树反序列化为 User 对象
User? user = doc.GetValue<User>("user");

// 安全版本
if (doc.TryGetValue<User>("user", out var u))
{
    Console.WriteLine(u.Name);
}

重要:GetValue<T> 走的是 System.Text.Json 默认行为——大小写敏感且按属性名匹配。建议给类加 [JsonPropertyName("xxx")] 注解,确保字段名与数据源一致:

using System.Text.Json.Serialization;

public class User
{
    [JsonPropertyName("name")]  public string Name { get; set; } = "";
    [JsonPropertyName("age")]   public int    Age  { get; set; }
    [JsonPropertyName("active")] public bool  Active { get; set; }
}

7. 各格式约定

不同格式在解析成同一棵树时,有一些映射约定需要了解,否则可能取不到值。

7.1 JSON

  • 对象 → Object,数组 → Array,标量(含数字/布尔/null)→ Value。
  • JSON 的数字、布尔、null 会记住原始类型,因此 GetDouble / As<T> 都能得到正确类型(不仅仅是字符串)。
{
  "user": { "name": "Ada", "age": 36, "active": true },
  "items": [ { "id": 1, "tag": "a" }, { "id": 2, "tag": "b" } ]
}
doc.GetString("user.name");      // "Ada"
doc.GetInt("user.age");          // 36
doc.GetBool("user.active");      // true
doc.GetString("items[1].tag");   // "b"

7.2 XML

约定:

  • 根元素本身即路径起点(与 JSON 根对象一致,路径里不含根标签名)。例如根元素是 <root>,则路径从 person 开始,而不是 root.person。
  • 元素属性用 @ 前缀访问:person.@id
  • 混合文本(元素既有属性/子元素又有直接文本)用 #text 访问
  • 同名的重复兄弟元素会自动合并成数组
<root>
  <person id="7" type="staff">
    <name>张三</name>
    <phone>123</phone>
    <phone>456</phone>
  </person>
</root>
doc.GetString("person.@id");          // "7"(属性,根元素 root 是路径起点)
doc.GetString("person.name");         // "张三"
doc.GetString("person.phone[0]");     // "123"(phone 重复 → 数组)
doc.GetString("person.phone[1]");     // "456"

XML 命名空间声明(xmlns)会被忽略,属性用本地名(LocalName)暴露。

7.3 CSV

  • 第一行作为表头,后续每一行被解析成一个对象,用表头字段名作为键。
  • 整体是一个 Array,每行是一个 Object。
  • 支持 RFC-4180:"..." 引号字段、"" 转义、引号内可含逗号与换行。
  • 可通过 doc.Get("0").GetString("列名") 按行号访问(行号从 0 开始,对应表头之后的第一行)。
name,age,city
Alice,30,Beijing
Bob,25,Shanghai
doc.Count;                          // 2(两行数据)
doc.GetString("0.name");           // "Alice"(第 1 行)
doc.GetString("1.city");           // "Shanghai"(第 2 行)
doc.GetInt("0.age");               // 30

表头为空时,该列用列号(0、1、2…)作为键。数据行字段数少于表头时,缺失字段取空字符串。

7.4 纯文本 TXT

ParseText 的判定逻辑:

  • 若大多数非空行形如 key: 值 或 key = 值(含 key=value、key: value、key="值"),则整体解析为 Object,按名字取。
  • 否则整体解析为 Array(每行一个元素)。
  • 原始文本保留在 doc.SourceText 中,随时可取。
  • 以 # 或 ; 开头的行视为注释,会被忽略。
  • 同名键出现多次时,自动合并为数组。
# 配置
host = 127.0.0.1
port = 8080
tag = a
tag = b
doc.GetString("host");             // "127.0.0.1"
doc.GetInt("port");                // 8080
doc.GetString("tag[0]");           // "a"(tag 出现两次 → 数组)
doc.GetString("tag[1]");           // "b"
doc.SourceText;                    // 原始全文

若文本是纯段落(无 key=value 结构):

第一行内容
第二行内容
doc.GetString("0");                // "第一行内容"
doc.GetString("1");                // "第二行内容"

7.5 INI

约定:

  • [section] 下的键值,用 doc.GetString("节名.键名") 访问。
  • 不在任何节下的键,归入 _global 节:doc.GetString("_global.键名")。
  • 支持 key = value、key: value、# / ; 注释、带引号的值。
  • 节名与键名不区分大小写。
[server]
host = 127.0.0.1
port = 5432

[auth]
user = admin
doc.GetString("server.host");      // "127.0.0.1"
doc.GetInt("server.port");         // 5432
doc.GetString("auth.user");        // "admin"

8. 编码与乱码处理

乱码(mojibake)几乎总是因为「字节被用错误的代码页解码」——最典型的就是 UTF-8 字节被当成 Latin-1 / Windows-1252 读取,比如 Greuther Fürth 变成 Greuther Fürth。

8.1 读取文件时指定正确编码

ParseFile 默认就能自动识别大多数情况,绝大多数文件不需要你手动传 Encoding:

  • 文件带 BOM(UTF-8 / UTF-16 / UTF-32)→ 自动识别并跳过 BOM;
  • 无 BOM 但字节是合法 UTF-8(现代文件几乎都是这种)→ 按 UTF-8 读取;
  • 无 BOM 且字节不是合法 UTF-8 → 几乎可以断定是旧的单字节代码页(Latin-1 / Windows-1252),自动回退到 Windows-1252(找不到则用 Latin-1),无需你指定。

也就是说,像 Greuther Fürth 这种按旧代码页保存的文件,现在直接 DataParser.ParseFile("data.json") 就能读到正确中文/德文字符,不用再写 Encoding.Latin1。

只有当你明确知道编码、且想强制覆盖自动判断时,才显式传参数(显式编码永远优先):

using System.Text;

// 强制按 Latin-1 读取(覆盖自动判断)
var doc = DataParser.ParseFile("data.json", Encoding.Latin1);

// 或 Windows-1252
var doc2 = DataParser.ParseFile("data.json", Encoding.GetEncoding("Windows-1252"));

ParseStream 同样支持编码参数,且同样具备上述自动识别/回退逻辑:

using var stream = File.OpenRead("data.json");
var doc = DataParser.ParseStream(stream);                 // 自动识别
var doc2 = DataParser.ParseStream(stream, Encoding.Latin1); // 强制指定

为什么 Latin-1「不能 100% 单独识别」?因为 Latin-1 把 0–255 每个字节都映射成字符,任何字节流在 Latin-1 下都「合法」,所以它没有签名、没有结构约束,无法自证身份。库能做的最合理推断就是「不是 UTF-8 ⇒ 多半是旧代码页」并回退过去。

8.2 修复「已经被污染」的字符串

如果字符串在上游就已经被错误解码(你拿到的是 "Fürth" 这种),用 TextFixer 修:

using DataKit;

string dirty = GetJsonFromSomewhere();        // 里面是 "Greuther Fürth"
string clean = TextFixer.FixMojibake(dirty);  // "Greuther Fürth"
var doc = DataParser.ParseJson(clean);
  • 默认会依次尝试用 Latin1 和 Windows-1252 重新取字节、再用 UTF-8 解码,取第一个「无替换符、且内容有变化」的结果。
  • 如果你确定当初被错误解码用的是哪个代码页,可以显式传入,避免误判:
string clean = TextFixer.FixMojibake(dirty, Encoding.Latin1);
  • 安全兜底:如果修复后仍然含替换符 `` 或内容没有任何变化,则原样返回,绝不会二次损坏本身正确的文本。
TextFixer.FixMojibake("Greuther Fürth");   // 原样返回 "Greuther Fürth"(无变化)

如果你遇到的乱码形态不常见(不是典型的「UTF-8→Latin1」路径),把实际出问题的那一行原文贴给我,我可以在 TextFixer 里补充对应的反解码规则,精准修掉它。


9. 重新序列化 / 导出

可以把解析后的文档(或任意子树)重新导成 JSON:

string json = doc.ToJson();                 // 整篇文档
string json2 = doc.Get("user").ToJsonString();   // 某个子树

// 拿到 JsonNode,便于继续用 System.Text.Json 处理
System.Text.Json.Nodes.JsonNode? node = doc.ToJsonNode();

注意:XML / CSV / INI / TXT 解析出来的树,重新 ToJson() 会得到一份等效的 JSON 表示,方便你在不同格式间转换。


10. 错误处理

解析或取值失败时,统一抛出 DataKitException(自定义异常类型,位于 DataKit 命名空间):

  • 格式非法(如 JSON 括号不匹配、XML 标签不闭合)→ Parse* 时抛 DataKitException。
  • 路径解析不到 / 类型不匹配 → Get / Get* 时抛 DataKitException。

建议写法:

try
{
    int age = doc.GetInt("user.age");
}
catch (DataKitException ex)
{
    Console.WriteLine("取值失败:" + ex.Message);
}

// 或者更推荐:用 TryGet / TryGetValue 避免异常
if (doc.TryGetValue<int>("user.age", out var age))
{
    // 使用 age
}

11. 完整示例

示例 A:解析 JSON 并取值

using DataKit;

string json = """
{
  "user": {
    "name": "Ada",
    "age": 36,
    "address": { "city": "London" },
    "roles": ["admin", "editor"]
  },
  "match": [
    { "id": 3, "name": "alpha" },
    { "id": 5, "name": "beta" }
  ]
}
""";

var doc = DataParser.ParseJson(json);

string name  = doc.GetString("user.name");        // "Ada"
int    age   = doc.GetInt("user.age");            // 36
string city  = doc.GetString("user.address.city");// "London"
string role0 = doc.GetString("user.roles[0]");    // "admin"
string m5    = doc.GetString("match[id=5].name"); // "beta"(谓词过滤)

Console.WriteLine($"{name}, {age}, {city}, {role0}, {m5}");

示例 B:解析 XML 文件 + 处理编码

using DataKit;
using System.Text;

// 文件按 Latin-1 保存,显式指定编码避免乱码
var doc = DataParser.ParseFile("people.xml", Encoding.Latin1);

string id   = doc.GetString("person.@id");  // 属性用 @,根元素 root 是路径起点
string name = doc.GetString("person.name");

示例 C:解析 CSV 并遍历

using DataKit;

var doc = DataParser.ParseCsv(csvText);
for (int r = 0; r < doc.Count; r++)
{
    string name = doc.GetString($"{r}.name");
    int    age  = doc.GetInt($"{r}.age");
    Console.WriteLine($"{name} ({age})");
}

示例 D:解析 TXT / INI 配置

using DataKit;

var cfg = DataParser.ParseIni(iniText);
string host = cfg.GetString("server.host");
int    port = cfg.GetInt("server.port");

var txt = DataParser.ParseText(textContent);
if (txt.TryGet("title", out var title))
{
    Console.WriteLine(title.AsString());
}

示例 E:从 REST API 获取数据

REST 响应本质是「字符串或字节流」,直接喂给 DataParser 即可,与来源无关。

using DataKit;
using System.Net.Http;

var http = new HttpClient();

// 模式 1:拿到字符串(HttpClient 已按 Content-Type 的 charset 解码成 .NET 字符串)
string body = await http.GetStringAsync("https://api.example.com/user/1");
var doc = DataParser.ParseJson(body);          // 已知是 JSON
// 或不确定格式:var doc = DataParser.Parse(body);  // 以 { 或 [ 开头 → JSON,以 < 开头 → XML
string name = doc.GetString("user.name");
string tag  = doc.GetString("match[id=5].n");  // 沿用路径谓词语法

// 模式 2:拿到流(更省内存,不先把整个响应拼成字符串)
using var stream = await http.GetStreamAsync("https://api.example.com/user/1");
var doc2 = DataParser.ParseStream(stream, format: DataFormat.Json);
int age = doc2.GetInt("user.age");

// XML 响应同理
string xmlBody = await http.GetStringAsync("https://api.example.com/person/7");
var xmlDoc = DataParser.ParseXml(xmlBody);
string pid = xmlDoc.GetString("person.@id");   // 根元素 person 是路径起点

关于编码:REST 响应的字节已由 HttpClient 按 Content-Type 里的 charset(默认 UTF-8)正确解码成字符串,所以一般不会出现文件那种乱码问题。只有当接口错误地声明了 charset、导致字符串已经被污染时,才需要 TextFixer.FixMojibake(body) 兜底修复。


12. 常见问题 FAQ

Q1:我的 .NET Framework 4.x 项目能用吗? A:类库默认多目标 net8.0;net9.0。需要把 DataKit.csproj 里的 TargetFrameworks 改成 netstandard2.0 后重新编译,即可被 .NET Framework 4.6.1+ 引用(功能基本一致,部分新语法会退化为兼容写法)。

Q2:match[id=5] 返回多条 id=5 时怎么办? A:当前只返回第一条命中。如需「全部」,请在路径语法中增加「返回全部」标记(如 match[id=5]*),可联系维护者补充。

Q3:取值类型不对会怎样? A:GetInt("name") 对字符串 "Ada" 会抛 DataKitException。不确定的字段优先用 TryGetValue<T>。

Q4:为什么 GetValue<User> 反序列化出来是 null / 字段为空? A:底层是 System.Text.Json,默认大小写敏感。确认类属性名与 JSON 键一致,或加 [JsonPropertyName("xxx")]。

Q5:中文/特殊字符乱码怎么解决? A:见第 8 节。优先在 ParseFile/ParseStream 传入正确 Encoding;若字符串已污染,用 TextFixer.FixMojibake 修复。

Q6:能不能解析超大文件(几百 MB)? A:当前解析会把内容一次性读入内存。超大文件场景可联系维护者增加「流式解析」模式。

Q7:支持 YAML 吗? A:当前支持 JSON / XML / TXT / CSV / INI。YAML 可按需补充。


文档与源码保持一致。DataKit 是零依赖、线程安全的类库,所有静态入口方法均可安全并发调用。

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 111 7/20/2026
1.0.0 114 7/20/2026