Sage.Data.Extensions 1.0.1.1

dotnet add package Sage.Data.Extensions --version 1.0.1.1
                    
NuGet\Install-Package Sage.Data.Extensions -Version 1.0.1.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="Sage.Data.Extensions" Version="1.0.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sage.Data.Extensions" Version="1.0.1.1" />
                    
Directory.Packages.props
<PackageReference Include="Sage.Data.Extensions" />
                    
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 Sage.Data.Extensions --version 1.0.1.1
                    
#r "nuget: Sage.Data.Extensions, 1.0.1.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 Sage.Data.Extensions@1.0.1.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=Sage.Data.Extensions&version=1.0.1.1
                    
Install as a Cake Addin
#tool nuget:?package=Sage.Data.Extensions&version=1.0.1.1
                    
Install as a Cake Tool

Sage.Data.Extensions

NuGet License

简介

Sage.Data.Extensions 提供了一系列常用的数据类型扩展方法,简化了日常开发中的常见操作。该库设计为线程安全,并完全兼容 AOT 编译。

特性

  • 字符串扩展方法(判空、格式化、类型转换等)
  • 日期时间扩展方法(格式化、时间段计算等)
  • 字节数组扩展方法(编码转换、哈希计算等)
  • 整型和长整型扩展方法(范围检查、格式化等)
  • 字典扩展方法(条件添加、转换为查询字符串等)
  • JsonNode扩展方法(空数组处理等)
  • 文件路径处理方法(获取文件名、扩展名、目录名、路径组合等)
  • 显示文本处理方法(条件格式化、标题转换、无效值处理等)
  • 线程安全设计
  • 完全兼容 AOT 编译

安装

dotnet add package Sage.Data.Extensions

使用示例

字符串扩展方法 (StringExtensions)

空值检查和默认值处理
// 判断字符串是否为空(null、空字符串或仅包含空白字符)
string text = "";
bool isEmpty = text.IsEmpty(); // 返回 true

string text2 = "  ";
bool isEmpty2 = text2.IsEmpty(); // 返回 true

string text3 = "Hello";
bool isEmpty3 = text3.IsEmpty(); // 返回 false

// 判断字符串是否为null或空字符串(不考虑空白字符)
string text4 = "  ";
bool isNullOrEmpty = text4.IsNullOrEmpty(); // 返回 false

// 设置默认值
string nullText = null;
string result = nullText.DefaultIfEmpty("N/A"); // 返回 "N/A"
类型转换
// 字符串转整数
string numText = "123";
int num = numText.ToInt(); // 返回 123

// 自动处理非数字字符
string mixedText = "a123b";
int num2 = mixedText.ToInt(); // 返回 123

// 转换失败时使用默认值
string invalidText = "abc";
int num3 = invalidText.ToInt(10); // 返回 10

// 转换为其他数值类型
string longText = "9876543210";
long longNum = longText.ToLong();

string shortText = "123";
short shortNum = shortText.ToShort();

字节数组扩展方法 (ByteExtensions)

编码转换
// 转换为Base64字符串
byte[] data = Encoding.UTF8.GetBytes("Hello World");
string base64 = data.ToBase64String(); // 返回 "SGVsbG8gV29ybGQ="

// 转换为十六进制字符串
byte[] bytes = { 0xFF, 0x00, 0xAB };
string hex = bytes.ToHexString(); // 返回 "FF00AB"
string hexLower = bytes.ToHexStringLower(); // 返回 "ff00ab"

// 转换为URL安全的Base64
byte[] urlData = Encoding.UTF8.GetBytes("Hello+World/=");
string urlSafe = urlData.ToUrlSafeBase64(); // 返回不含+、/和=的Base64字符串

// 转换为UTF-8字符串
byte[] utf8Bytes = Encoding.UTF8.GetBytes("Hello 世界");
string text = utf8Bytes.ToUtf8String(); // 返回 "Hello 世界"
哈希计算
// 计算HMAC-SHA1
byte[] data = Encoding.UTF8.GetBytes("重要数据");
string key = "secret-key";
byte[] hmacBytes = data.ToHmacSha1(key);

// 转换为Base64用于存储或传输
string signature = Convert.ToBase64String(hmacBytes);

文件路径处理方法

// 获取文件名
string filePath = @"C:\Users\Username\Documents\report.pdf";
string fileName = filePath.GetFileName(); // 返回 "report.pdf"

// 获取文件扩展名
string extension = filePath.GetExtension(); // 返回 ".pdf"

// 获取目录名
string directory = filePath.GetDirectoryName(); // 返回 "C:\Users\Username\Documents"

// 从右侧截取字符串
string text = "Hello World";
string right = text.Right(5); // 返回 "World"

// 组合路径
string basePath = @"C:\Users\Username";
string fullPath = basePath.CombinePath("Documents", "Projects", "MyApp");
// 返回 "C:\Users\Username\Documents\Projects\MyApp"

日期时间扩展方法 (DateTimeExtensions)

格式化
// 根据与当前日期的关系格式化日期
DateTime now = DateTime.Now;
string formatted = now.ToFriendlyDateString(); // 返回如 "14:30"

DateTime yesterday = DateTime.Now.AddDays(-1);
string formatted2 = yesterday.ToFriendlyDateString(); // 返回如 "12日 14:30"

// 日志格式化
string logTime = now.ToLogFormat(); // 返回 "2023-12-20 14:30:45"
string logTimeWithMs = now.ToLogFormat(true); // 返回 "2023-12-20 14:30:45.123"

// 友好日期格式化
// 今天的日期会显示为 "14:30"
// 昨天的日期会显示为 "12日 14:30"
// 上个月的日期会显示为 "5月12日 14:30"
// 去年的日期会显示为 "23年5月12日 14:30"

// 获取月份的开始和结束日期
DateTime date = new DateTime(2023, 5, 15);
DateTime firstDay = date.StartOfMonth(); // 返回 2023-05-01 00:00:00
DateTime lastDay = date.EndOfMonth(); // 返回 2023-05-31 23:59:59
日期计算
// 获取日期的开始和结束时间
DateTime date = DateTime.Now;
DateTime dayStart = date.StartOfDay(); // 返回当天 00:00:00.000
DateTime dayEnd = date.EndOfDay(); // 返回当天 23:59:59.999

// 获取周、月、季度、年的开始和结束
DateTime weekStart = date.StartOfWeek(); // 返回本周一 00:00:00.000
DateTime monthStart = date.StartOfMonth(); // 返回本月1日 00:00:00.000
DateTime monthEnd = date.EndOfMonth(); // 返回本月最后一天 23:59:59.999
DateTime quarterStart = date.StartOfQuarter(); // 返回本季度第一天 00:00:00.000
DateTime yearStart = date.StartOfYear(); // 返回本年1月1日 00:00:00.000

// 工作日判断
bool isWorkday = date.IsWeekday(); // 如果是周一至周五返回true
bool isWeekend = date.IsWeekend(); // 如果是周六或周日返回true

// 日期差异计算
DateTime futureDate = DateTime.Now.AddDays(10);
int daysUntil = DateTime.Now.DaysUntil(futureDate); // 返回10

// Unix时间戳转换
long timestamp = date.ToUnixTimestamp(); // 返回Unix时间戳(秒)
long timestampMs = date.ToUnixTimestampMs(); // 返回Unix时间戳(毫秒)

整型扩展方法 (IntExtensions)

范围检查和限制
// 判断数值是否在指定范围内
int age = 25;
bool isAdult = age.Between(18, 100); // 返回 true

// 限制数值在指定范围内
int score = 150;
int clampedScore = score.Clamp(0, 100); // 返回 100

int volume = -5;
int safeVolume = volume.Clamp(0, 100); // 返回 0
重复执行操作
// 重复执行指定次数的操作
5.Times(i => Console.WriteLine($"第 {i + 1} 次执行"));

// 创建测试数据
var items = new List<string>();
3.Times(i => items.Add($"Item {i + 1}")); // 添加3个元素到列表

// 批量处理
10.Times(i => ProcessBatch(i)); // 执行10次批处理操作
时间转换
// 将整数转换为TimeSpan
int timeout = 30; // 30秒
TimeSpan timeoutSpan = timeout.Seconds();

int cacheMinutes = 15;
TimeSpan expiry = cacheMinutes.Minutes();

int sessionHours = 2;
TimeSpan session = sessionHours.Hours();

int retentionDays = 30;
TimeSpan retention = retentionDays.Days();
数值格式化和判断
// 转换为二进制和十六进制字符串
int number = 10;
string binary = number.ToBinary(); // 返回 "1010"

int color = 255;
string hex = color.ToHexString(); // 返回 "FF"
string hexLower = color.ToHexString(false); // 返回 "ff"

// 判断奇偶性
int value = 42;
bool isEven = value.IsEven(); // 返回 true
bool isOdd = value.IsOdd(); // 返回 false

// 重复执行操作
var items = new List<string>();
5.Times(i => items.Add($"Item {i + 1}")); // 添加5个项目到列表

长整型扩展方法 (LongExtensions)

文件大小格式化
// 格式化文件大小
long fileSize = 1536; 
string size1 = fileSize.ToFileSizeString(); // 返回 "1.50 KB"
string size2 = fileSize.ToFileSizeString(0); // 返回 "2 KB"

long largeSize = 1073741824; 
string size3 = largeSize.ToFileSizeString(); // 返回 "1.00 GB"
时间戳转换
// Unix时间戳转换为DateTime
long timestamp = 1609459200; // 2021-01-01 00:00:00 UTC
DateTime date = timestamp.FromUnixTimestamp(); 

// 毫秒时间戳转换
long timestampMs = 1609459200000; // 2021-01-01 00:00:00.000 UTC
DateTime dateMs = timestampMs.FromUnixTimestampMs();
其他操作
// 范围检查和限制
long score = 85;
bool isPassing = score.Between(60, 100); // 返回 true

long value = 150;
long clampedValue = value.Clamp(0, 100); // 返回 100

// 毫秒转TimeSpan
long duration = 5000; // 5秒
TimeSpan timeSpan = duration.ToTimeSpan();

// 判断奇偶性
long number = 42;
bool isEven = number.IsEven(); // 返回 true
bool isOdd = number.IsOdd(); // 返回 false
JsonNode扩展方法 (JsonNodeExtensions)
// 将JsonNode转换为对象,如果是空数组则返回null
JsonNode? node = JsonNode.Parse("{\"name\":\"test\"}");
User? user = node.ToObjectOrNull<User>(JsonContext.Default.User);

// 处理空数组情况
JsonNode? emptyArray = JsonNode.Parse("[]");
User? nullUser = emptyArray.ToObjectOrNull<User>(JsonContext.Default.User); // 返回null

显示文本处理方法 (StringExtensions)

// 将无效值转换为默认显示文本
string birth = "0000-00-00 00:00:00";
string displayText = birth.ToDisplayText(["0000-00-00 00:00:00"], "暂无数据");  // 返回 "暂无数据"

string nullValue = null;
string displayText2 = nullValue.ToDisplayText("N/A", "暂无数据");  // 返回 "暂无数据"

// 日期显示文本处理
string dateStr = "2023-05-15";
string formattedDate = dateStr.ToDateDisplayText();  // 返回 "2023-05-15"

string invalidDate = "0000-00-00";
string formattedInvalidDate = invalidDate.ToDateDisplayText();  // 返回 "暂无数据"

string customFormatDate = "2023-05-15";
string formattedCustomDate = customFormatDate.ToDateDisplayText("无", "yyyy年MM月dd日");  // 返回 "2023年05月15日"

// 数字格式化显示
string number = "1234567.89";
string formattedNumber = number.ToFormattedNumber(2);  // 返回 "1,234,567.89"
string formattedCurrency = number.ToFormattedNumber("C2");  // 返回 "¥1,234,567.89"

// 文件大小友好显示
string fileSize = "1048576";
string readableSize = fileSize.ToReadableFileSize();  // 返回 "1.00 MB"

// 枚举友好文本显示
var statusMappings = new Dictionary<string, string>
{
    {"0", "禁用"},
    {"1", "启用"},
    {"2", "维护中"}
};
string statusCode = "1";
string friendlyStatus = statusCode.ToFriendlyText(statusMappings);  // 返回 "启用"

// 条件格式化文本
string status = "1";
string display = status.ConditionalText(s => s == "1", "启用", "禁用");  // 返回 "启用"

// 将字符串转换为标题格式(每个单词首字母大写)
string text = "hello world";
string title = text.ToTitleCase();  // 返回 "Hello World"

string mixed = "tHIS iS a TeST";
string titleMixed = mixed.ToTitleCase();  // 返回 "This Is A Test"

字典扩展方法 (DictionaryExtensions)


// 定义枚举
public enum MemberStatus
{
    Inactive = 0,
    Active = 1,
    Suspended = 2,
    Premium = 3
}
public enum OrderType
{
    Online = 1,
    Offline = 2,
    Wholesale = 3
}
public enum PaymentMethod
{
    Cash,
    Card,
    Alipay,
    WeChat
}
public enum Gender
{
    Unknown = 0,
    Male = 1,
    Female = 2
}
public enum SortOrder
{
    Asc,
    Desc
}

var businessParams = new Dictionary<string, object>
{
["member_id"] = memberId
}
.AddIfNotEmpty("keywords", keywords)
.AddIfGreaterThan("page", page)
.AddIfGreaterThan("pagesize", pagesize)
    
// ✨ 枚举转数字
.AddIfValid("status", status,
    s => s.HasValue,
    s => (int)s!.Value)
    
// ✨ 枚举转自定义字符串
.AddIfValid("order_type", orderType,
    t => t.HasValue,
    t => t!.Value switch
{
    OrderType.Online => "online_order",
    OrderType.Offline => "offline_order",
    OrderType.Wholesale => "wholesale_order",
    _ => "unknown"
})
    
// ✨ 枚举转API代码
.AddIfValid("payment_method", paymentMethod,
    p => p.HasValue,
    p => p!.Value switch
{
    PaymentMethod.Cash => "CASH_001",
    PaymentMethod.Card => "CARD_002",
    PaymentMethod.Alipay => "ALIPAY_003",
    PaymentMethod.WeChat => "WECHAT_004",
    _ => "UNKNOWN_000"
})
    
// ✨ 有条件的枚举转换(只有非Unknown时才添加)
.AddIfValid("gender", gender,
    g => g.HasValue && g.Value != Gender.Unknown,
    g => (int)g!.Value)
    
// ✨ 枚举转布尔值
.AddIfValid("is_desc", sortOrder,
    s => s.HasValue,
    s => s!.Value == SortOrder.Desc)
    
// ✨ 布尔值转数字
.AddIfValid("is_vip", isVip,
    v => v.HasValue,
    v => v!.Value ? 1 : 0)
    
// ✨ 布尔值转字符串
.AddIfValid("include_deleted", includeDeleted,
    d => d.HasValue,
    d => d!.Value ? "yes" : "no")
    
// ✨ 复杂条件 + 多重转换
.AddIfValid("priority_level", status,
    s => s.HasValue && (s.Value == MemberStatus.Premium || s.Value == MemberStatus.Active),
    s => s!.Value switch
{
    MemberStatus.Premium => 100,
    MemberStatus.Active => 50,
    _ => 0
})
    
// ✨ 日期时间转时间戳
.AddIfValid("created_after_timestamp", createdAfter,
    d => d.HasValue && d.Value > DateTime.MinValue,
    d => ((DateTimeOffset)d!.Value).ToUnixTimeSeconds())
    
// ✨ 组合条件:只有VIP且状态为Active时才添加特殊标识
.AddIfValid("special_flag", status,
    s => s.HasValue && s.Value == MemberStatus.Premium && isVip == true,
    s => "VIP_PREMIUM")
    
// ✨ 多枚举组合逻辑
.AddIfValid("service_level", new { Status = status, OrderType = orderType },
    combo => combo.Status.HasValue && combo.OrderType.HasValue,
    combo => (combo.Status!.Value, combo.OrderType!.Value) switch
{
    (MemberStatus.Premium, OrderType.Wholesale) => "enterprise",
    (MemberStatus.Premium, _) => "premium",
    (MemberStatus.Active, OrderType.Wholesale) => "business",
    (MemberStatus.Active, _) => "standard",
    _ => "basic"
});

// 转换为查询字符串
var queryString = businessParams.ToQueryString();

// 转换为 JSON
var jsonString = businessParams.ToJsonString();

更多方法查看代码文档。
字典扩展方法 (日期类型更多示例)
var parameters = new Dictionary<string, object>();

// 使用 List<string>
var dateList = new List<string> { "2024-01-01 00:00:00", "2024-01-31 23:59:59" };
parameters.AddIfValidDateRange("create_time", dateList);

// 使用 string[]
var dateArray = new string[] { "2024-01-01 00:00:00", "2024-01-31 23:59:59" };
parameters.AddIfValidDateRange("create_time", dateArray);

// 使用 IEnumerable<string>
IEnumerable<string> dateEnumerable = new[] { "2024-01-01 00:00:00", "2024-01-31 23:59:59" };
parameters.AddIfValidDateRange("create_time", dateEnumerable);

// 空集合 - 不会添加
List<string>? emptyList = null;
parameters.AddIfValidDateRange("create_time", emptyList);

// 只有一个元素 - 不会添加
var singleDate = new List<string> { "2024-01-01 00:00:00" };
parameters.AddIfValidDateRange("create_time", singleDate);

// 超过两个元素 - 不会添加
var threeDates = new List<string> { "2024-01-01", "2024-01-15", "2024-01-31" };
parameters.AddIfValidDateRange("create_time", threeDates);

Console.WriteLine(parameters.ToQueryString());
// 输出: create_time=2024-01-01%2000%3A00%3A00&create_time=2024-01-31%2023%3A59%3A59


var parameters = new Dictionary<string, object>();

// 有效的日期时间格式 - 会添加
var validDates = new List<string> { "2024-01-01 00:00:00", "2024-01-31 23:59:59" };
parameters.AddIfValidDateRange("create_time", validDates, validateDateTime: true);

// 无效的日期时间格式 - 不会添加
var invalidDates = new List<string> { "invalid-date", "2024-01-31 23:59:59" };
parameters.AddIfValidDateRange("create_time", invalidDates, validateDateTime: true);

// 包含空字符串 - 不会添加
var emptyStringDates = new List<string> { "", "2024-01-31 23:59:59" };
parameters.AddIfValidDateRange("create_time", emptyStringDates, validateDateTime: true);

// 不验证格式(默认行为)- 会添加任何两个字符串
var anyStrings = new List<string> { "任意字符串1", "任意字符串2" };
parameters.AddIfValidDateRange("create_time", anyStrings, validateDateTime: false);

Console.WriteLine(parameters.ToQueryString());

var parameters = new Dictionary<string, object>();

// 正确的时间顺序 - 会添加
var correctOrder = new List<string> { "2024-01-01 00:00:00", "2024-01-31 23:59:59" };
parameters.AddIfValidDateRangeWithOrder("create_time", correctOrder);

// 相同的时间 - 会添加
var sameTime = new List<string> { "2024-01-15 12:00:00", "2024-01-15 12:00:00" };
parameters.AddIfValidDateRangeWithOrder("update_time", sameTime);

// 错误的时间顺序 - 不会添加
var wrongOrder = new List<string> { "2024-01-31 23:59:59", "2024-01-01 00:00:00" };
parameters.AddIfValidDateRangeWithOrder("create_time", wrongOrder);

// 无效的日期格式 - 不会添加
var invalidFormat = new List<string> { "2024-13-01", "2024-01-32" };
parameters.AddIfValidDateRangeWithOrder("create_time", invalidFormat);

Console.WriteLine(parameters.ToQueryString());

字典扩展方法 (索引数组的示例)
// 支持 List<string>
var couponIds = new List<string> { "123", "456", "789" };
businessParams.AddIndexedArray("coupon_id", couponIds);
/* 结果:
coupon_id[0] = "123"
coupon_id[1] = "456" 
coupon_id[2] = "789"
*/

// 支持 string[]
var couponArray = new[] { "123", "456", "789" };
businessParams.AddIndexedArray("coupon_id", couponArray);
/* 结果:
coupon_id[0] = "123"
coupon_id[1] = "456"
coupon_id[2] = "789"
*/

// 支持 IList<string>
IList<string> couponIList = new List<string> { "123", "456", "789" };
businessParams.AddIndexedArray("coupon_id", couponIList);
/* 结果:
coupon_id[0] = "123"
coupon_id[1] = "456"
coupon_id[2] = "789"
*/

// 支持 int[]
var categoryIds = new[] { 1, 2, 3 };
businessParams.AddIndexedArray("category_id", categoryIds);
/* 结果:
category_id[0] = 1
category_id[1] = 2
category_id[2] = 3
*/

// 支持 List<int>
var productIds = new List<int> { 100, 200, 300, 400 };
businessParams.AddIndexedArray("product_id", productIds);
/* 结果:
product_id[0] = 100
product_id[1] = 200
product_id[2] = 300
product_id[3] = 400
*/

// 支持 IList<int>
IList<int> orderIds = new List<int> { 10, 20, 30 };
businessParams.AddIndexedArray("order_id", orderIds);
/* 结果:
order_id[0] = 10
order_id[1] = 20
order_id[2] = 30
*/

// 支持 long[]
var userIds = new long[] { 1000000001L, 1000000002L, 1000000003L };
businessParams.AddIndexedArray("user_id", userIds);
/* 结果:
user_id[0] = 1000000001
user_id[1] = 1000000002
user_id[2] = 1000000003
*/

// 支持 List<long>
var transactionIds = new List<long> { 9999999999L, 8888888888L };
businessParams.AddIndexedArray("transaction_id", transactionIds);
/* 结果:
transaction_id[0] = 9999999999
transaction_id[1] = 8888888888
*/

// 单个元素
var singleCoupon = new[] { "SINGLE001" };
businessParams.AddIndexedArray("coupon_id", singleCoupon);
/* 结果:
coupon_id[0] = "SINGLE001"
*/

// 带条件检查,自动过滤空值
var mixedIds = new[] { "123", "", "456", null };
businessParams.AddIndexedArrayIfNotEmpty("coupon_id", mixedIds);
/* 结果(空字符串和null被过滤):
coupon_id[0] = "123"
coupon_id[1] = "456"
*/

// List<string> 过滤空值
var mixedCouponList = new List<string> { "C001", "  ", "C002", null, "C003" };
businessParams.AddIndexedArrayIfNotEmpty("coupon_id", mixedCouponList);
/* 结果(空白字符串和null被过滤):
coupon_id[0] = "C001"
coupon_id[1] = "C002"
coupon_id[2] = "C003"
*/

// IList<string> 过滤空值
IList<string> mixedTagIds = new List<string> { "tag1", "", "tag2", null, "tag3" };
businessParams.AddIndexedArrayIfNotEmpty("tag_id", mixedTagIds);
/* 结果(空值被过滤):
tag_id[0] = "tag1"
tag_id[1] = "tag2"
tag_id[2] = "tag3"
*/

// int[] 条件添加
var validCategoryIds = new[] { 1, 2, 3 };
businessParams.AddIndexedArrayIfNotEmpty("category_id", validCategoryIds);
/* 结果:
category_id[0] = 1
category_id[1] = 2
category_id[2] = 3
*/

// List<int> 条件添加
var validIds = new List<int> { 10, 20, 30 };
businessParams.AddIndexedArrayIfNotEmpty("id", validIds);
/* 结果:
id[0] = 10
id[1] = 20
id[2] = 30
*/

// 数值范围验证 - 所有值都大于0
var ids = new[] { 1, 2, 3 };
businessParams.AddIndexedArrayIfAllGreaterThan("id", ids, 0);
/* 结果(所有值都大于0,全部添加):
id[0] = 1
id[1] = 2
id[2] = 3
*/

// 数值范围验证 - 包含无效值(包含0或负数)
var invalidIds = new[] { 1, 0, 3, -1 };
businessParams.AddIndexedArrayIfAllGreaterThan("id", invalidIds, 0);
/* 结果(因为包含<=0的值,整个数组不会被添加):
无任何参数添加
*/

// List<int> 数值范围验证 - 全部有效
var validCategoryIds2 = new List<int> { 5, 10, 15, 20 };
businessParams.AddIndexedArrayIfAllGreaterThan("category_id", validCategoryIds2, 0);
/* 结果(所有值都大于0):
category_id[0] = 5
category_id[1] = 10
category_id[2] = 15
category_id[3] = 20
*/

// List<int> 数值范围验证 - 包含无效值
var mixedCategoryIds = new List<int> { 5, 10, 0, 20 };
businessParams.AddIndexedArrayIfAllGreaterThan("category_id", mixedCategoryIds, 0);
/* 结果(包含0,整个数组不会被添加):
无任何参数添加
*/

// 自定义最小值验证
var priceIds = new[] { 100, 200, 300 };
businessParams.AddIndexedArrayIfAllGreaterThan("price_id", priceIds, 50);
/* 结果(所有值都大于50):
price_id[0] = 100
price_id[1] = 200
price_id[2] = 300
*/

// null 数组处理
string[]? nullArray = null;
businessParams.AddIndexedArray("coupon_id", nullArray);
/* 结果(null被忽略):
无任何参数添加
*/

// null 列表处理
List<string>? nullList = null;
businessParams.AddIndexedArrayIfNotEmpty("coupon_id", nullList);
/* 结果(null被忽略):
无任何参数添加
*/

// 空数组处理
var emptyArray = new string[] { };
businessParams.AddIndexedArray("coupon_id", emptyArray);
/* 结果(空数组被忽略):
无任何参数添加
*/

// 空列表处理
var emptyList = new List<string>();
businessParams.AddIndexedArrayIfNotEmpty("coupon_id", emptyList);
/* 结果(空列表被忽略):
无任何参数添加
*/

// 全部为null或空字符串的数组
var allEmptyArray = new[] { "", null, "  ", null };
businessParams.AddIndexedArrayIfNotEmpty("coupon_id", allEmptyArray);
/* 结果(所有元素都被过滤):
无任何参数添加
*/

// 多种类型组合使用
var comboCouponIds = new List<string> { "C001", "C002", "C003" };
var comboCategoryIds = new[] { 10, 20, 30 };
var comboTagIds = new[] { "hot", "", "new", null, "sale" };
var comboUserIds = new long[] { 1000001L, 1000002L };
var comboValidIds = new[] { 1, 2, 3 };
var comboInvalidIds = new[] { 1, 0, 3 };

var businessParams = new Dictionary<string, object>
{
    ["member_id"] = 12345,
    ["action"] = "batch_operation"
}
.AddIndexedArray("coupon_id", comboCouponIds)
.AddIndexedArray("category_id", comboCategoryIds)
.AddIndexedArrayIfNotEmpty("tag_id", comboTagIds)
.AddIndexedArray("user_id", comboUserIds)
.AddIndexedArrayIfAllGreaterThan("valid_id", comboValidIds, 0)
.AddIndexedArrayIfAllGreaterThan("invalid_id", comboInvalidIds, 0);

/* 完整结果:
member_id = 12345
action = "batch_operation"
coupon_id[0] = "C001"
coupon_id[1] = "C002"
coupon_id[2] = "C003"
category_id[0] = 10
category_id[1] = 20
category_id[2] = 30
tag_id[0] = "hot"
tag_id[1] = "new"
tag_id[2] = "sale"
user_id[0] = 1000001
user_id[1] = 1000002
valid_id[0] = 1
valid_id[1] = 2
valid_id[2] = 3
(invalid_id不会被添加,因为包含0)
*/

// 实际业务方法使用
var memberCouponIds = new List<string> { "CPN001", "CPN002", "CPN003" };
var businessParams2 = new Dictionary<string, object>
{
    ["member_id"] = 12345,
}
.AddIndexedArrayIfNotEmpty("coupon_id", memberCouponIds);

/* businessParams2 结果:
member_id = 12345
coupon_id[0] = "CPN001"
coupon_id[1] = "CPN002"
coupon_id[2] = "CPN003"
*/

// 包含特殊字符的字符串
var specialCoupons = new[] { "COUP&ON1", "COUP=ON2", "COUP ON3" };
businessParams.AddIndexedArray("coupon_id", specialCoupons);
/* 结果:
coupon_id[0] = "COUP&ON1"
coupon_id[1] = "COUP=ON2"
coupon_id[2] = "COUP ON3"

查询字符串(URL编码后):
coupon_id[0]=COUP%26ON1&coupon_id[1]=COUP%3DON2&coupon_id[2]=COUP%20ON3
*/

// 中文字符处理
var chineseCoupons = new[] { "优惠券1", "优惠券2" };
businessParams.AddIndexedArray("coupon_id", chineseCoupons);
/* 结果:
coupon_id[0] = "优惠券1"
coupon_id[1] = "优惠券2"
*/

// 超长数组
var longArray = new string[100];
for (int i = 0; i < 100; i++) { longArray[i] = $"item{i}"; }
businessParams.AddIndexedArray("items", longArray);
/* 结果:
items[0] = "item0"
items[1] = "item1"
...
items[99] = "item99"

查询字符串:
items[0]=item0&items[1]=item1&...&items[99]=item99
*/

// 混合类型在同一字典中
var mixedBusinessParams = new Dictionary<string, object>
{
    ["user_id"] = 999,
    ["status"] = "active"
}
.AddIndexedArray("coupon_ids", new[] { "A", "B", "C" })
.AddIndexedArray("category_ids", new[] { 1, 2, 3 })
.AddIndexedArrayIfNotEmpty("tag_ids", new[] { "hot", "", "new" })
.AddIndexedArrayIfAllGreaterThan("price_ranges", new[] { 100, 200, 300 }, 50);

/* 结果:
user_id = 999
status = "active"
coupon_ids[0] = "A"
coupon_ids[1] = "B"
coupon_ids[2] = "C"
category_ids[0] = 1
category_ids[1] = 2
category_ids[2] = 3
tag_ids[0] = "hot"
tag_ids[1] = "new"
price_ranges[0] = 100
price_ranges[1] = 200
price_ranges[2] = 300

字典扩展方法 (字典类型的转换) DEMO
using System;
using System.Collections.Generic;
using Sage.Data.Extensions;

namespace DictionaryExtensionsExamples
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("=== 字典扩展方法使用示例 ===\n");

            // ========================================
            // 1. 基础值类型转换方法
            // ========================================
            Console.WriteLine("【1. 基础值类型转换】");
            BasicTypeConversion();

            // ========================================
            // 2. 键类型转换方法
            // ========================================
            Console.WriteLine("\n【2. 键类型转换】");
            KeyTypeConversion();

            // ========================================
            // 3. Dictionary 与 SortedDictionary 相互转换
            // ========================================
            Console.WriteLine("\n【3. Dictionary 与 SortedDictionary 相互转换】");
            DictionarySortedDictionaryConversion();

            // ========================================
            // 4. 常用类型转换便捷方法
            // ========================================
            Console.WriteLine("\n【4. 常用类型转换便捷方法】");
            CommonTypeConversions();

            // ========================================
            // 5. 常用排序场景的便捷方法
            // ========================================
            Console.WriteLine("\n【5. 常用排序场景】");
            SortingScenarios();

            // ========================================
            // 6. 高级转换方法
            // ========================================
            Console.WriteLine("\n【6. 高级转换方法】");
            AdvancedConversions();

            Console.WriteLine("\n=== 示例结束 ===");
            Console.ReadKey();
        }

        // ========================================
        // 1. 基础值类型转换方法
        // ========================================
        static void BasicTypeConversion()
        {
            // 1.1 ToDictionary<TValue> - 基础转换
            Console.WriteLine("1.1 ToDictionary<TValue> - 基础转换");
            var source1 = new Dictionary<string, object>
            {
                { "age", 25 },
                { "score", "100" },  // 字符串会被自动转换为int
                { "level", 5 }
            };
            var intDict = source1.ToDictionary<int>();
            Console.WriteLine($"  age={intDict["age"]}, score={intDict["score"]}, level={intDict["level"]}");

            // 1.2 ToSortedDictionary<TValue> - SortedDictionary 转换
            Console.WriteLine("\n1.2 ToSortedDictionary<TValue> - SortedDictionary 转换");
            var sortedSource = new SortedDictionary<string, object>
            {
                { "price", 99.99m },
                { "discount", "10.5" }  // 字符串转为decimal
            };
            var decimalSorted = sortedSource.ToSortedDictionary<decimal>();
            foreach (var kvp in decimalSorted)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 1.3 ToDictionarySafe<TValue> - 安全转换(跳过失败的项)
            Console.WriteLine("\n1.3 ToDictionarySafe<TValue> - 安全转换");
            var mixedSource = new Dictionary<string, object>
            {
                { "age", 25 },
                { "name", "John" },      // 这个无法转为int,会被跳过
                { "score", 100 },
                { "address", "Beijing" } // 这个也会被跳过
            };
            var safeIntDict = mixedSource.ToDictionarySafe<int>();
            Console.WriteLine($"  成功转换的项数: {safeIntDict.Count}");
            foreach (var kvp in safeIntDict)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 1.4 ToSortedDictionarySafe<TValue> - SortedDictionary 安全转换
            Console.WriteLine("\n1.4 ToSortedDictionarySafe<TValue> - SortedDictionary 安全转换");
            var mixedSorted = new SortedDictionary<string, object>
            {
                { "count", 10 },
                { "description", "测试" },
                { "total", "50" }
            };
            var safeIntSorted = mixedSorted.ToSortedDictionarySafe<int>();
            Console.WriteLine($"  成功转换的项数: {safeIntSorted.Count}");
            foreach (var kvp in safeIntSorted)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 1.5 ToDictionary<TValue>(defaultValue) - 带默认值的转换
            Console.WriteLine("\n1.5 ToDictionary<TValue>(defaultValue) - 带默认值转换");
            var withDefault = mixedSource.ToDictionary<int>(0);
            Console.WriteLine($"  转换后的项数: {withDefault.Count}");
            foreach (var kvp in withDefault)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 1.6 ToSortedDictionary<TValue>(defaultValue) - SortedDictionary 带默认值
            Console.WriteLine("\n1.6 ToSortedDictionary<TValue>(defaultValue) - 带默认值");
            var sortedWithDefault = mixedSorted.ToSortedDictionary<int>(-1);
            foreach (var kvp in sortedWithDefault)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }
        }

        // ========================================
        // 2. 键类型转换方法
        // ========================================
        static void KeyTypeConversion()
        {
            // 2.1 ToDictionary<TKey, TValue>(keyConverter) - 键转换
            Console.WriteLine("2.1 ToDictionary<TKey, TValue>(keyConverter) - 键转换");
            var stringKeyDict = new Dictionary<string, object>
            {
                { "1", 100 },
                { "2", 200 },
                { "10", 1000 }
            };
            var intKeyDict = stringKeyDict.ToDictionary<int, int>(key => int.Parse(key));
            foreach (var kvp in intKeyDict)
            {
                Console.WriteLine($"  Key={kvp.Key} (int), Value={kvp.Value}");
            }

            // 2.2 ToDictionary<TKey, TValue>(keyConverter, valueConverter) - 键值同时转换
            Console.WriteLine("\n2.2 ToDictionary<TKey, TValue> - 键值同时转换");
            var allStringDict = new Dictionary<string, object>
            {
                { "100", "10.5" },
                { "200", "20.8" },
                { "300", "30.2" }
            };
            var convertedDict = allStringDict.ToDictionary<int, decimal>(
                key => int.Parse(key),
                value => decimal.Parse(value.ToString()!)
            );
            foreach (var kvp in convertedDict)
            {
                Console.WriteLine($"  Key={kvp.Key} (int), Value={kvp.Value} (decimal)");
            }

            // 2.3 ToSortedDictionary<TKey, TValue>(keyConverter) - SortedDictionary 键转换
            Console.WriteLine("\n2.3 ToSortedDictionary<TKey, TValue>(keyConverter)");
            var sortedStringKey = new SortedDictionary<string, object>
            {
                { "5", "Apple" },
                { "2", "Banana" },
                { "8", "Cherry" }
            };
            var sortedIntKey = sortedStringKey.ToSortedDictionary<int, string>(
                key => int.Parse(key)
            );
            Console.WriteLine("  排序后的结果:");
            foreach (var kvp in sortedIntKey)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 2.4 ToSortedDictionary<TKey, TValue>(keyConverter, valueConverter) - 完整转换
            Console.WriteLine("\n2.4 ToSortedDictionary<TKey, TValue> - 键值完整转换");
            var fullConvert = new SortedDictionary<string, object>
            {
                { "10", "100.5" },
                { "5", "50.2" },
                { "15", "150.8" }
            };
            var fullConverted = fullConvert.ToSortedDictionary<int, double>(
                key => int.Parse(key),
                value => double.Parse(value.ToString()!)
            );
            foreach (var kvp in fullConverted)
            {
                Console.WriteLine($"  {kvp.Key} => {kvp.Value}");
            }
        }

        // ========================================
        // 3. Dictionary 与 SortedDictionary 相互转换
        // ========================================
        static void DictionarySortedDictionaryConversion()
        {
            // 3.1 ToSortedDictionary() - Dictionary 转 SortedDictionary
            Console.WriteLine("3.1 ToSortedDictionary() - Dictionary 转 SortedDictionary");
            var unsortedDict = new Dictionary<string, object>
            {
                { "zebra", 3 },
                { "apple", 1 },
                { "banana", 2 }
            };
            var sorted = unsortedDict.ToSortedDictionary();
            Console.WriteLine("  排序后:");
            foreach (var kvp in sorted)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 3.2 ToDictionary() - SortedDictionary 转 Dictionary
            Console.WriteLine("\n3.2 ToDictionary() - SortedDictionary 转 Dictionary");
            var sortedDict = new SortedDictionary<string, object>
            {
                { "a", 1 },
                { "b", 2 },
                { "c", 3 }
            };
            var normalDict = sortedDict.ToDictionary();
            Console.WriteLine($"  转换后类型: {normalDict.GetType().Name}");
            Console.WriteLine($"  项数: {normalDict.Count}");

            // 3.3 ToSortedDictionary<TValue>() - 带类型转换的排序
            Console.WriteLine("\n3.3 ToSortedDictionary<TValue> - 带类型转换排序");
            var mixedDict = new Dictionary<string, object>
            {
                { "z-score", "100" },
                { "a-level", 5 },
                { "m-count", "50" }
            };
            var sortedTyped = mixedDict.ToSortedDictionary<int>();
            foreach (var kvp in sortedTyped)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 3.4 ToDictionary<TValue>() - SortedDictionary 带类型转换
            Console.WriteLine("\n3.4 ToDictionary<TValue> - SortedDictionary 类型转换");
            var typedSorted = new SortedDictionary<string, object>
            {
                { "price", "99.99" },
                { "discount", 10.5m },
                { "tax", "5.5" }
            };
            var typedDict = typedSorted.ToDictionary<decimal>();
            foreach (var kvp in typedDict)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value:F2}");
            }

            // 3.5 ToSortedDictionarySafe<TValue>() - 安全转换排序
            Console.WriteLine("\n3.5 ToSortedDictionarySafe<TValue> - 安全转换排序");
            var mixedForSafe = new Dictionary<string, object>
            {
                { "valid1", 10 },
                { "invalid", "not a number" },
                { "valid2", 20 }
            };
            var safeSorted = mixedForSafe.ToSortedDictionarySafe<int>();
            Console.WriteLine($"  成功转换: {safeSorted.Count} 项");
            foreach (var kvp in safeSorted)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 3.6 ToSortedDictionary<TKey, TValue>(keyConverter) - 键转换排序
            Console.WriteLine("\n3.6 ToSortedDictionary<TKey, TValue> - 键转换排序");
            var keyConvertDict = new Dictionary<string, object>
            {
                { "3", "Three" },
                { "1", "One" },
                { "2", "Two" }
            };
            var keySorted = keyConvertDict.ToSortedDictionary<int, string>(
                key => int.Parse(key)
            );
            foreach (var kvp in keySorted)
            {
                Console.WriteLine($"  {kvp.Key} => {kvp.Value}");
            }

            // 3.7 ToSortedDictionary<TKey, TValue>(keyConverter, valueConverter) - 完整转换排序
            Console.WriteLine("\n3.7 ToSortedDictionary<TKey, TValue> - 完整转换排序");
            var fullDict = new Dictionary<string, object>
            {
                { "100", "10.5" },
                { "50", "5.2" },
                { "200", "20.8" }
            };
            var fullSorted = fullDict.ToSortedDictionary<int, decimal>(
                key => int.Parse(key),
                value => decimal.Parse(value.ToString()!)
            );
            foreach (var kvp in fullSorted)
            {
                Console.WriteLine($"  {kvp.Key} => {kvp.Value}");
            }

            // 3.8 自定义比较器示例
            Console.WriteLine("\n3.8 使用自定义比较器(忽略大小写)");
            var caseDict = new Dictionary<string, object>
            {
                { "Name", 1 },
                { "age", 2 },
                { "ADDRESS", 3 }
            };
            var caseSorted = caseDict.ToSortedDictionary(StringComparer.OrdinalIgnoreCase);
            foreach (var kvp in caseSorted)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }
        }

        // ========================================
        // 4. 常用类型转换便捷方法
        // ========================================
        static void CommonTypeConversions()
        {
            // 4.1 ToStringDictionary() - 转为字符串字典
            Console.WriteLine("4.1 ToStringDictionary() - 转为字符串字典");
            var mixedDict = new Dictionary<string, object>
            {
                { "age", 25 },
                { "price", 99.99m },
                { "active", true },
                { "date", DateTime.Now }
            };
            var stringDict = mixedDict.ToStringDictionary();
            foreach (var kvp in stringDict)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value} (类型: {kvp.Value.GetType().Name})");
            }

            // 4.2 ToStringDictionary() - SortedDictionary 版本
            Console.WriteLine("\n4.2 ToStringDictionary() - SortedDictionary 版本");
            var sortedMixed = new SortedDictionary<string, object>
            {
                { "count", 100 },
                { "name", "Test" },
                { "enabled", false }
            };
            var sortedString = sortedMixed.ToStringDictionary();
            foreach (var kvp in sortedString)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 4.3 ToIntDictionary() - 转为整数字典
            Console.WriteLine("\n4.3 ToIntDictionary() - 转为整数字典");
            var numDict = new Dictionary<string, object>
            {
                { "age", 25 },
                { "score", "100" },
                { "level", 5 }
            };
            var intDict = numDict.ToIntDictionary();
            Console.WriteLine($"  Total: {intDict.Values.Sum()}");

            // 4.4 ToIntDictionary(defaultValue) - 带默认值
            Console.WriteLine("\n4.4 ToIntDictionary(defaultValue) - 带默认值");
            var mixedNum = new Dictionary<string, object>
            {
                { "valid", 10 },
                { "invalid", "abc" },
                { "another", 20 }
            };
            var intWithDefault = mixedNum.ToIntDictionary(0);
            foreach (var kvp in intWithDefault)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 4.5 ToLongDictionary() - 转为长整数字典
            Console.WriteLine("\n4.5 ToLongDictionary() - 转为长整数字典");
            var bigNumDict = new Dictionary<string, object>
            {
                { "bignum1", 1000000000L },
                { "bignum2", "2000000000" }
            };
            var longDict = bigNumDict.ToLongDictionary();
            foreach (var kvp in longDict)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value:N0}");
            }

            // 4.6 ToLongDictionary(defaultValue) - 带默认值
            Console.WriteLine("\n4.6 ToLongDictionary(defaultValue) - 带默认值");
            var mixedLong = new Dictionary<string, object>
            {
                { "valid", 999999999999L },
                { "invalid", "not-a-number" }
            };
            var longWithDefault = mixedLong.ToLongDictionary(0L);
            foreach (var kvp in longWithDefault)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 4.7 ToDecimalDictionary() - 转为小数字典
            Console.WriteLine("\n4.7 ToDecimalDictionary() - 转为小数字典");
            var priceDict = new Dictionary<string, object>
            {
                { "price", 99.99m },
                { "discount", "10.5" },
                { "tax", 5.5 }
            };
            var decimalDict = priceDict.ToDecimalDictionary();
            foreach (var kvp in decimalDict)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value:C}");
            }

            // 4.8 ToDecimalDictionary(defaultValue) - 带默认值
            Console.WriteLine("\n4.8 ToDecimalDictionary(defaultValue) - 带默认值");
            var mixedDecimal = new Dictionary<string, object>
            {
                { "amount", 100.50m },
                { "invalid", "xyz" }
            };
            var decimalWithDefault = mixedDecimal.ToDecimalDictionary(0m);
            foreach (var kvp in decimalWithDefault)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 4.9 ToBoolDictionary() - 转为布尔字典
            Console.WriteLine("\n4.9 ToBoolDictionary() - 转为布尔字典");
            var flagDict = new Dictionary<string, object>
            {
                { "enabled", true },
                { "active", "true" },
                { "visible", false }
            };
            var boolDict = flagDict.ToBoolDictionary();
            foreach (var kvp in boolDict)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 4.10 ToDateTimeDictionary() - 转为日期时间字典
            Console.WriteLine("\n4.10 ToDateTimeDictionary() - 转为日期时间字典");
            var dateDict = new Dictionary<string, object>
            {
                { "created", DateTime.Now },
                { "modified", "2024-01-01" },
                { "expires", new DateTime(2025, 12, 31) }
            };
            var dateTimeDict = dateDict.ToDateTimeDictionary();
            foreach (var kvp in dateTimeDict)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value:yyyy-MM-dd}");
            }

            // 4.11 ToGuidDictionary() - 转为 GUID 字典
            Console.WriteLine("\n4.11 ToGuidDictionary() - 转为 GUID 字典");
            var guid1 = Guid.NewGuid();
            var guid2 = Guid.NewGuid();
            var guidDict = new Dictionary<string, object>
            {
                { "id1", guid1 },
                { "id2", guid2.ToString() }
            };
            var guidDictResult = guidDict.ToGuidDictionary();
            foreach (var kvp in guidDictResult)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }
        }

        // ========================================
        // 5. 常用排序场景的便捷方法
        // ========================================
        static void SortingScenarios()
        {
            // 5.1 ToSortedStringDictionary() - 排序字符串字典
            Console.WriteLine("5.1 ToSortedStringDictionary() - 排序字符串字典");
            var unsorted = new Dictionary<string, object>
            {
                { "name", "John" },
                { "age", 25 },
                { "city", "Beijing" }
            };
            var sortedString = unsorted.ToSortedStringDictionary();
            Console.WriteLine("  按键排序:");
            foreach (var kvp in sortedString)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 5.2 ToSortedIntDictionary() - 排序整数字典
            Console.WriteLine("\n5.2 ToSortedIntDictionary() - 排序整数字典");
            var numUnsorted = new Dictionary<string, object>
            {
                { "z-score", 100 },
                { "a-level", 5 },
                { "m-count", 50 }
            };
            var sortedInt = numUnsorted.ToSortedIntDictionary();
            foreach (var kvp in sortedInt)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 5.3 ToSortedDictionaryIgnoreCase() - 忽略大小写排序
            Console.WriteLine("\n5.3 ToSortedDictionaryIgnoreCase() - 忽略大小写排序");
            var caseDict = new Dictionary<string, object>
            {
                { "Name", 1 },
                { "age", 2 },
                { "ADDRESS", 3 },
                { "City", 4 }
            };
            var caseIgnoreSorted = caseDict.ToSortedDictionaryIgnoreCase();
            Console.WriteLine("  忽略大小写排序:");
            foreach (var kvp in caseIgnoreSorted)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 5.4 ToSortedDictionaryNatural() - 自然排序(数字感知)
            Console.WriteLine("\n5.4 ToSortedDictionaryNatural() - 自然排序");
            var naturalDict = new Dictionary<string, object>
            {
                { "item10", "第10项" },
                { "item2", "第2项" },
                { "item1", "第1项" },
                { "item20", "第20项" },
                { "item3", "第3项" }
            };
            var naturalSorted = naturalDict.ToSortedDictionaryNatural();
            Console.WriteLine("  自然排序结果 (item1, item2, item3, item10, item20):");
            foreach (var kvp in naturalSorted)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 对比普通排序
            Console.WriteLine("\n  对比: 普通字母排序 (item1, item10, item2, item20, item3):");
            var normalSorted = naturalDict.ToSortedDictionary();
            foreach (var kvp in normalSorted)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }
        }

        // ========================================
        // 6. 高级转换方法
        // ========================================
        static void AdvancedConversions()
        {
            // 6.1 ToDictionaryWhere<TValue>() - 条件过滤转换
            Console.WriteLine("6.1 ToDictionaryWhere<TValue> - 条件过滤转换");
            var mixedDict = new Dictionary<string, object>
            {
                { "age", 25 },
                { "score", 100 },
                { "name", "John" },
                { "level", "5" },
                { "address", "Beijing" }
            };
            
            // 只转换可以转为 int 的项
            var filteredInt = mixedDict.ToDictionaryWhere<int>(
                kvp => kvp.Value is int || 
                       (kvp.Value is string s && int.TryParse(s, out _))
            );
            Console.WriteLine("  只包含可转为int的项:");
            foreach (var kvp in filteredInt)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 只转换值大于某个数的项
            var filteredLarge = mixedDict.ToDictionaryWhere<int>(
                kvp => {
                    if (kvp.Value is int i) return i > 50;
                    if (kvp.Value is string s && int.TryParse(s, out var n)) return n > 50;
                    return false;
                }
            );
            Console.WriteLine("\n  只包含值大于50的项:");
            foreach (var kvp in filteredLarge)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 6.2 TryToDictionary<TValue>() - 尝试转换
            Console.WriteLine("\n6.2 TryToDictionary<TValue> - 尝试转换");
            
            // 成功的转换
            var validDict = new Dictionary<string, object>
            {
                { "age", 25 },
                { "score", "100" },
                { "level", 5 }
            };
            if (validDict.TryToDictionary<int>(out var successResult))
            {
                Console.WriteLine("  ✓ 转换成功!");
                Console.WriteLine($"  转换了 {successResult.Count} 项");
                foreach (var kvp in successResult)
                {
                    Console.WriteLine($"  {kvp.Key}={kvp.Value}");
                }
            }
            else
            {
                Console.WriteLine("  ✗ 转换失败");
            }

            // 失败的转换
            var invalidDict = new Dictionary<string, object>
            {
                { "age", 25 },
                { "name", "John" },  // 这个无法转为int
                { "score", 100 }
            };
            if (invalidDict.TryToDictionary<int>(out var failResult))
            {
                Console.WriteLine("\n  ✓ 转换成功");
            }
            else
            {
                Console.WriteLine("\n  ✗ 转换失败 (包含无法转换的项)");
                Console.WriteLine($"  结果字典项数: {failResult.Count}");
            }

            // 6.3 复杂场景组合示例
            Console.WriteLine("\n6.3 复杂场景组合示例");
            var complexDict = new Dictionary<string, object>
            {
                { "100", "张三" },
                { "50", "李四" },
                { "200", "王五" },
                { "30", "赵六" }
            };

            // 先转换键为int,再排序,再过滤出ID大于50的
            var complexResult = complexDict
                .ToDictionary<int, string>(key => int.Parse(key))  // 键转为int
                .Where(kvp => kvp.Key > 50)                        // 过滤
                .OrderBy(kvp => kvp.Key)                           // 排序
                .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);   // 转回Dictionary

            Console.WriteLine("  ID大于50的用户 (按ID排序):");
            foreach (var kvp in complexResult)
            {
                Console.WriteLine($"  ID={kvp.Key}, Name={kvp.Value}");
            }

            // 6.4 实际应用场景示例
            Console.WriteLine("\n6.4 实际应用场景 - API参数处理");
            var apiParams = new Dictionary<string, object>
            {
                { "page", "1" },
                { "pageSize", 20 },
                { "keyword", "测试" },
                { "status", null },      // null 值
                { "startDate", "" },     // 空字符串
                { "categoryId", "5" }
            };

            // 转换为字符串字典,移除空值
            var cleanParams = apiParams
                .Where(kvp => kvp.Value != null && 
                             (kvp.Value is not string s || !string.IsNullOrWhiteSpace(s)))
                .ToStringDictionary();

            Console.WriteLine("  清理后的API参数:");
            foreach (var kvp in cleanParams)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 生成查询字符串
            var queryString = string.Join("&", 
                cleanParams.Select(kvp => $"{kvp.Key}={kvp.Value}"));
            Console.WriteLine($"\n  查询字符串: {queryString}");
        }

        // ========================================
        // 额外示例:实际业务场景
        // ========================================
        static void RealWorldScenarios()
        {
            Console.WriteLine("\n【实际业务场景示例】");

            // 场景1:配置文件处理
            Console.WriteLine("\n场景1: 配置文件处理");
            var config = new Dictionary<string, object>
            {
                { "maxConnections", "100" },
                { "timeout", 30 },
                { "enableCache", "true" },
                { "cacheExpiration", "3600" }
            };

            var intConfig = config
                .Where(kvp => kvp.Key.Contains("max") || kvp.Key.Contains("timeout") || kvp.Key.Contains("Expiration"))
                .ToIntDictionary(0);

            Console.WriteLine("  整数配置项:");
            foreach (var kvp in intConfig)
            {
                Console.WriteLine($"  {kvp.Key}={kvp.Value}");
            }

            // 场景2:数据库查询结果转换
            Console.WriteLine("\n场景2: 数据库查询结果转换");
            var dbResult = new Dictionary<string, object>
            {
                { "UserId", 1001 },
                { "UserName", "张三" },
                { "Age", "28" },
                { "Salary", "8500.50" },
                { "IsActive", true }
            };

            // 按需转换不同类型
            var userId = dbResult.GetValueOrDefault<int>("UserId");
            var userName = dbResult.GetValueOrDefault<string>("UserName", "");
            var age = int.Parse(dbResult["Age"].ToString()!);
            var salary = decimal.Parse(dbResult["Salary"].ToString()!);

            Console.WriteLine($"  用户信息: ID={userId}, 姓名={userName}, 年龄={age}, 薪资={salary:C}");

            // 场景3:商品分类排序
            Console.WriteLine("\n场景3: 商品分类排序");
            var categories = new Dictionary<string, object>
            {
                { "category10", "电子产品" },
                { "category2", "图书" },
                { "category1", "食品" },
                { "category20", "服装" },
                { "category3", "家居" }
            };

            var sortedCategories = categories.ToSortedDictionaryNatural();
            Console.WriteLine("  自然排序的分类:");
            foreach (var kvp in sortedCategories)
            {
                Console.WriteLine($"  {kvp.Key} => {kvp.Value}");
            }

            // 场景4:多语言配置
            Console.WriteLine("\n场景4: 多语言配置");
            var i18n = new Dictionary<string, object>
            {
                { "Welcome", "欢迎" },
                { "goodbye", "再见" },
                { "HELLO", "你好" },
                { "Thanks", "谢谢" }
            };

            var i18nSorted = i18n.ToSortedDictionaryIgnoreCase();
            Console.WriteLine("  忽略大小写排序的翻译:");
            foreach (var kvp in i18nSorted)
            {
                Console.WriteLine($"  {kvp.Key} => {kvp.Value}");
            }
        }
    }
}

许可证

本项目采用 Apache 2.0 许可证。详情请参阅 LICENSE 文件。

贡献

欢迎提交问题报告和改进建议。如果您想贡献代码,请提交拉取请求。

作者

  • LiuPengLai - 甲壳虫科技 欢迎提交问题和功能请求。 QQ Group: 1054304346
Product Compatible and additional computed target framework versions.
.NET 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 is compatible.  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.
  • net10.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Sage.Data.Extensions:

Package Downloads
Sage.CloudStorage.Qiniu

Sage.CloudStorage.Qiniu 是一个基于 .NET 平台的现代化七牛云存储 SDK,采用完全异步设计,提供了对七牛云对象存储、CDN 等服务的简单易用的 API 封装。该库基于 Sage.Http 构建,具有高性能、可扩展的七牛云服务访问能力,特别适合企业级应用和大文件处理场景。 ## 核心优势 - **现代化API设计**:完全异步,符合.NET最佳实践 - **模块化架构**:各组件职责明确,易于扩展和维护 - **丰富的事件机制**:提供上传进度通知和完成事件 - **智能上传策略**:自动选择最佳上传方式和分片大小 - **完善的错误处理**:提供详细的错误信息和恢复机制 ## 功能特性 - **完整的对象存储支持**:上传、下载、管理、删除等操作 - **高级上传功能**: - 智能分片上传(自动优化分片大小) - 断点续传支持 - 并发控制 - 实时进度监控 - **CDN管理**:刷新、预取、带宽查询、日志下载 - **数据处理**:图片处理、音视频转码等 - **批量操作**:批量上传、删除等

Sage.Encryption

Sage.Encryption 提供了加密和解密功能,支持多种加密算法,支持Windows安全存储等。 - AES 加密/解密 - AES-GCM 加密/解密 - Windows 安全数据存储 - 同步和异步 API - 完全兼容 AOT 编译

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1.1 289 10/25/2025
1.0.0.22 252 10/25/2025
1.0.0.21 313 10/15/2025
1.0.0.20 319 10/15/2025
1.0.0.19 440 10/15/2025 1.0.0.19 is deprecated.
1.0.0.18 364 10/13/2025
1.0.0.17 343 10/5/2025
1.0.0.16 329 10/5/2025
1.0.0.15 334 10/5/2025
1.0.0.14 269 10/4/2025
1.0.0.13 335 10/3/2025
1.0.0.12 372 10/2/2025
1.0.0.11 352 10/2/2025
1.0.0.10 338 10/1/2025
1.0.0.9 346 10/1/2025
1.0.0.8 345 10/1/2025
1.0.0.7 295 9/28/2025
1.0.0.6 274 9/27/2025
1.0.0.5 328 9/26/2025
1.0.0.4 439 8/24/2025
Loading failed

丰富字典转换功能