Aore.Toolkit 1.0.0

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

Aore.Toolkit

零依赖的 .NET 通用工具库:面向「函数处理 + 集合操作」,覆盖函数处理管线(防抖、节流、记忆化缓存、重试、限流、熔断器)、对象池、带缓存反射、线程安全单例、迭代器与双向链表 / 列表 / 队列 / 堆栈等集合工具。

  • 零 NuGet 依赖:核心库不引用任何第三方包,算法、反射加速、并发原语一律本地实现。
  • 7 个目标框架:netstandard2.0 / net462 / net472 / net48 / net8.0 / net9.0 / net10.0。
  • 生产就绪基线:0 错误 0 警告编译、单元测试覆盖 net48 + net8.0、中文 XML 注释(IntelliSense 友好)。

本文档是 NuGet 包内嵌说明文档(PackageReadmeFile),每次新增模块后请同步更新本文档的「能力清单」「API 方法清单」「API 完整使用方法」与「注意事项」。

能力清单

命名空间 能力
Aore.Toolkit.Pooling ObjectPool<T> 通用对象池、共享池门面
Aore.Toolkit.Reflection ReflectionCache 带缓存反射工具、ReflectionExtensions
Aore.Toolkit.Patterns SingletonBase<T> 单例基类、Singleton<T> 普通泛型单例
Aore.Toolkit.Collections Iterator 迭代器工具类、IIterator<T> / EnumerableIterator<T> 迭代器模式游标、DoublyLinkedList<T> 双向链表、ListExtensions 列表扩展、QueueExtensions / Deque<T> 队列工具、StackExtensions / MinMaxStack<T> 堆栈工具
Aore.Toolkit.Functions FuncExtensions 函数处理方法、Debouncer 防抖、Throttle 节流、Memoizer<TKey, TValue> 函数缓存(记忆化)
Aore.Toolkit.Resilience IClock 时间源、IRateLimiter 限流(令牌桶 / 固定窗口 / 滑动窗口 / 并发限制)、CircuitBreaker 熔断器、CircuitBreakerRegistry 命名注册表

安装

dotnet add package Aore.Toolkit

或从源码引用:将 src/Aore.Toolkit 工程作为项目引用加入解决方案。

快速上手

using Aore.Toolkit.Pooling;
using Aore.Toolkit.Reflection;
using Aore.Toolkit.Collections;
using Aore.Toolkit.Functions;
using Aore.Toolkit.Resilience;

// 迭代器工具:惰性序列 + 迭代器模式游标
Iterator.Range(1, 3);                  // 1, 2, 3(惰性)
Iterator.Window(items, 3);             // 滑动窗口
var cursor = Iterator.Create(items);   // 可重置读游标

// 双向链表:任意位置 O(1) 插入 / 移动(LRU 核心结构)
var order = new DoublyLinkedList<string>();
order.MoveToFront("A");

// 通用对象池:复用高频对象,减少内存分配
var sb = ObjectPool.StringBuilderPool.Rent();
try
{
  sb.Append("Aore").Append('.');
  // ...
}
finally
{
  ObjectPool.StringBuilderPool.Return(sb);   // 自动 Clear()
}

// 带缓存反射:命中后零反射分配
var getter = ReflectionCache.GetPropertyGetter(typeof(User), nameof(User.Name));
var userName = (string)getter(user);

// 函数缓存(记忆化):LRU + 命中率统计
var cache = ((Func<string, Type>)ResolveType).Memoize(capacity: 128);
cache.Get("User");
Console.WriteLine(cache.HitRate);

// 限流与熔断:保护下游
if (!bucket.TryAcquire()) { return TooManyRequests(); }   // 令牌桶
var user = breaker.Execute(() => UserService.Get(1));    // 熔断保护

API 方法清单

ObjectPool(Aore.Toolkit.Pooling,通用对象池)

成员 签名摘要 说明
ObjectPool<T>.ctor (Func<T> factory, Action<T>? reset = null, int maxRetained = 32, int preRent = 0) 工厂 + 复位回调 + 容量上限 + 预热
Rent () → T 池内有则复用,否则调用工厂新建
Return (T obj) → void 复位后入池;池满则丢弃(null 静默忽略)
Trim (int maxIdle) / () → void 裁剪空闲对象;无参等价 Clear()
Clear () → void 丢弃全部空闲对象
RetainedCount / CreatedCount / PeakRetainedCount int / long / int 空闲数 / 累计创建数 / 空闲峰值(命中率调优依据)
ObjectPool.For<T> () / (Func<T>) → IObjectPool<T> 取(或创建)类型 T 的全局共享池,同一 T 唯一
ObjectPool.StringBuilderPool → IObjectPool<StringBuilder> 内置 StringBuilder 池,归还自动 Clear()
ObjectPool.ClearSharedPools () → void / (Type) → void 丢弃全部共享池的空闲对象;Type 重载按类型清理
ObjectPool.RemoveShared<T> () / (Type) → bool 移除共享池(池退场并丢弃空闲对象);退场后 For<T> 重建全新池

ReflectionCache(Aore.Toolkit.Reflection,带缓存反射工具)

方法 签名摘要 说明
GetProperty / GetProperties (Type, string) → PropertyInfo? / (Type) → IReadOnlyList<PropertyInfo> 缓存属性查找(含基类 public 与非 public)
GetField (Type, string) → FieldInfo? 缓存字段查找
GetMethod (Type, string, Type?[]? = null) → MethodInfo? 按参数签名查找,重载歧义抛 AmbiguousMatchException
GetMethod (Type, string, int parameterCount) → MethodInfo? 按参数个数查找
GetConstructor (Type, Type?[]? = null) → ConstructorInfo? 按参数签名查找构造
GetNestedType (Type, string) → Type? 缓存嵌套类型查找
GetGenericArguments / GetGenericArgument (Type) → Type[] / (Type, int) → Type? 缓存泛型实参
GetElementType / TryGetElementType (Type) → Type? / (Type, out Type) → bool 解包数组与常见泛型容器接口(IEnumerable<T> / ICollection<T> / Task<T> 等)
IsNullable / GetUnderlyingType (Type) → bool / (Type) → Type? 可空判定与 Nullable<T> 解包
GetDefaultValue (Type) → object? 缓存的类型默认值
GetPropertyGetter / GetPropertySetter (Type, string) → Func<object, object?> / Action<object, object?>? 缓存的表达式树编译访问器(只读属性 setter 返回 null)
GetValue / SetValue (object, string) → object? / (object, string, object?) → void 走缓存委托的读写快捷方式
CacheCount / Clear int / () → void 缓存条目数(诊断)/ 清空缓存
Clear (Type) → int 按类型精准清除全部相关条目(插件卸载 / ALC 场景),返回移除条目数
HighWaterMark / TrimmedTypeCount int / long 条目总数预警水位(软上限,默认 0 = 关闭)/ 累计驱逐 Type 数(诊断)
ReflectionExtensions GetPropertyValue / SetPropertyValue / FindMethod / FindProperty / FindField 扩展方法形态的链式封装

单例(Aore.Toolkit.Patterns)

成员 签名摘要 说明
SingletonBase<T>.Instance → T 线程安全惰性单例(LazyThreadSafetyMode.ExecutionAndPublication)
SingletonBase<T>.IsCreated → bool 是否已构造(不触发构造)
SingletonBase<T>.OnSingletonCreated protected virtual void 子类一次性初始化钩子
SingletonBase<T>.DisposeInstance () → void 释放并丢弃实例(释放资源)
SingletonBase<T>.Reset () → void 丢弃实例引用,仅供单元测试
Singleton<T>.Instance / IsCreated / Reset 同上(无需继承) 普通泛型单例

Iterator / EnumerableIterator(Aore.Toolkit.Collections,迭代器)

方法 签名摘要 说明
Empty<T> () → IEnumerable<T> 空序列(共享单例,零分配)
Repeat<T> (T value, int count) → IEnumerable<T> 重复值 count 次(惰性)
Repeat<T> (T value) → IEnumerable<T> 无限重复同一值
RepeatSequence<T> (IEnumerable<T> source, int count) → IEnumerable<T> 整段重复数据源
Range (int start, int count) → IEnumerable<int> 连续整数(溢出前置检查)
Range (int start, int end, int step) → IEnumerable<int> 按步进区间;方向不匹配返回空
Cycle<T> (IEnumerable<T> source) → IEnumerable<T> 无限循环枚举
Batch<T> (IEnumerable<T>, int size) → IEnumerable<IReadOnlyList<T>> 不重叠分块,末块可短
Window<T> (IEnumerable<T>, int size) → IEnumerable<IReadOnlyList<T>> 滑动窗口
Create<T> (IEnumerable<T> source) → IIterator<T> 创建可重置读游标
IIterator<T> MoveNext / Current / HasNext / Position / Reset 迭代器模式:HasNext 不推进游标
EnumerableIterator<T>.Dispose () → void 释放底层枚举器(同时是 IEnumerator<T> / IEnumerable<T>)

DoublyLinkedList(Aore.Toolkit.Collections,双向链表)

成员 签名摘要 说明
构造 () / (int capacity) / (IEnumerable<T>) 空表 / 预留容量 / 由序列创建
Count / First / Last int / DoublyLinkedListNode<T>? 元素数 / 首节点 / 尾节点(空为 null)
FirstNode / LastNode DoublyLinkedListNode<T> 空链表抛 InvalidOperationException
AddFirst / AddLast / Add (T) → DoublyLinkedListNode<T> 头 / 尾插入并返回新节点
AddAfter / AddBefore (node, T) → void 指定节点后 / 前插入(O(1))
索引器 this[node] 按节点读写 Value
Remove (T) → bool / (node) → bool 按值 / 按节点删除;删除后节点导航清空
RemoveFirst / RemoveLast () → void 删除首 / 尾节点(空表抛异常)
Find / Contains / ForEach (T) → node? / (T) → bool / (Action<T>) 查找 / 判定 / 正向遍历
MoveToFirst / MoveToLast / MoveAfter / MoveBefore (node[, reference]) → void O(1) 移动节点(保持同一节点实例)
Reverse / Clear / ToArray () → ... 原地反转 / 清空 / 导出数组
CopyTo (T[], int) / (node[], int) 复制元素 / 节点
RemoveWhere / FindFirst / FindLast (Predicate<T>) → int / node? 按谓词批量删除与定位
InsertAfter / InsertBefore (value, referenceValue) → node 按值定位参考节点后插入(找不到则追加到尾部)
MoveToFront / MoveToBack (value) → bool LRU 两行搞定
ForEachBackward / ToDoublyLinkedList (Action<T>) / 静态 反向遍历 / 序列转链表

ListExtensions(Aore.Toolkit.Collections,列表操作与扩展)

方法 签名摘要 说明
AddRange (this IList, IEnumerable) → void 非泛型列表批量追加
InsertRange / ReplaceRange (this IList<T>, int, IEnumerable<T>) → void 区间插入 / 区间覆盖(不足则截断、更多则扩容)
GetRange (this IList<T>, int, int) → List<T> 导出区间副本(异常语义与 List<T>.GetRange 一致)
RemoveWhere / IndexOf (this IList<T>, Func<T, bool>) → int 谓词批量删除 / 定位下标
RemoveFirst / RemoveLast (this IList<T>, Func<T, bool>) → bool 删除首个 / 末个匹配项
Swap (this IList<T>, int, int) → void 交换两元素
ReverseInPlace (this IList<T>) → void 接口化原地反转
ShuffleInPlace / Shuffled (this IList<T>, Random?) → void / List<T> Fisher-Yates 洗牌 / 洗牌副本
Chunk (this IList<T>, int) → IEnumerable<IReadOnlyList<T>> 定长分块(惰性)
At / IsInRange (this IList<T>, int) → T / bool 安全取值(越界返回 default)/ 索引校验
Fill (this IList<T>, T, int, int) → void 区间填充
TryEnsureCapacity (this List<T>, int) → bool 容量不足时扩容,返回是否扩容
BinarySearchIndex (this IList<T>, T, IComparer<T>?) → int 二分查找(未命中返回按位补码插入点)
AddIf / AddIfNotNull (this IList<T>, bool, T) / (this IList<T>, T?) 条件 / 非空才追加

QueueExtensions / Deque(Aore.Toolkit.Collections,队列工具)

方法 签名摘要 说明
EnqueueRange / EnqueueIf / EnqueueIfNotNull (this Queue<T>, …) → void 批量 / 条件 / 非空入队
DequeueRange (this Queue<T>, int) → List<T> 批量出队(不足则取尽)
DequeueWhile (this Queue<T>, Func<T, bool>) → int 按谓词出队(只 Peek,保留剩余顺序)
DequeueAll (this Queue<T>) → T[] 一次性排空
Deque<T> PushFront / PushBack / PopFront / PopBack 双端队列(环形数组,摊还 O(1))
Deque<T> Try 系列 TryPopFront / TryPopBack / TryPeekFront / TryPeekBack 空队列返回 false
Deque<T> Count / IsEmpty / Clear / TrimExcess / ToArray 常规操作

StackExtensions / MinMaxStack(Aore.Toolkit.Collections,堆栈工具)

方法 签名摘要 说明
PushRange (this Stack<T>, IEnumerable<T>) → void 批量压栈(栈顶为源末元素)
PopRange / PopWhile / PopAll (this Stack<T>, …) → List<T> / int / T[] 批量弹出 / 按谓词弹出 / 排空
TryPop (this Stack<T>, out T) → bool 安全弹栈(net6+ 由 BCL 同名实例方法提供,语义一致)
MinMaxStack<T> (IComparer<T>?) / Push / Pop / Peek / TryPop 栈基础操作
MinMaxStack<T> GetMin / GetMax / TryGetMin / TryGetMax O(1) 最小 / 最大值查询

FuncExtensions(Aore.Toolkit.Functions,函数处理相关方法)

方法 签名摘要 说明
TryInvoke / TryInvoke\<T\> (this Action, out Exception?) → bool / (this Func<T>, out T?, out Exception?) → bool 安全调用并捕获可恢复异常(致命异常不吞)
InvokeSafely (this Action, Action<Exception>? onError = null) → void 事件回调场景:异常交给 onError 或吞掉
InvokeOrDefault (this Func<T>, T fallback, Action<Exception>? onError = null) → T 异常时返回兜底值
InvokeIf (this Action, bool) → void / (this Func<T>, bool, T) → T 条件成立才执行
InvokeWithTimeout (this Action, TimeSpan) → void / (this Func<T>, TimeSpan, T) → T 限时等待;超时抛 TimeoutException / 返回兜底值;无法终止已启动工作
Retry / Retry\<T\> (this Action / Func<T>, int maxAttempts = 3, TimeSpan? delay = null, Func<Exception,bool>? shouldRetry = null) 同步重试,耗尽重抛最后异常
RetryAsync / RetryAsync\<T\> (this Func<Task> / Func<Task<T>>, …, CancellationToken = default) 异步重试
Compose (this Func<T1,T2>, Func<T2,TResult>) → Func<T1,TResult> 函数组合 x => second(first(x))
MemoizeOnce (this Func<T>) → Func<T> 无参工厂的单键记忆化(Lazy<T> 单飞,异常也缓存)

Debouncer / Throttle(Aore.Toolkit.Functions,防抖与节流)

成员 签名摘要 说明
Debouncer (Action action, TimeSpan delay, Action<Exception>? onError = null) 防抖:静默期内连续触发只执行最后一次
Debouncer Invoke() / Flush() → bool / Cancel() / IsPending / Delay / Dispose() Flush 立即执行并返回 true
ThrottleMode enum { Leading, Trailing, LeadingAndTrailing } 触发模式
Throttle (Action action, TimeSpan interval, ThrottleMode mode = Leading, Action<Exception>? onError = null) 节流:窗口内最多执行一次
Throttle Invoke() → bool / Cancel() / Interval / Mode / Dispose() Invoke 返回本次是否真的执行

Memoizer(Aore.Toolkit.Functions,函数缓存 / 记忆化)

成员 签名摘要 说明
Memoizer<TKey,TValue> (Func<TKey,TValue> factory, int capacity = 128, IEqualityComparer<TKey>? = null, TimeSpan? ttl = null, Func<TKey,TValue,TimeSpan>? ttlSelector = null, IClock? = null) 线程安全 LRU 缓存;ttl / ttlSelector 启用惰性过期(默认永不过期)
Memoizer Get(key) → TValue 命中刷新 LRU;未命中计算后写入(工厂异常原样透传且不缓存)
Memoizer TryGet(key, out TValue?) → bool / ContainsKey(key) 只读缓存,不触发工厂
Memoizer Invalidate(key) → bool / Clear() 失效 / 清空
Memoizer Capacity / Count / Hits / Misses / HitRate 容量与命中率统计
Memoize (this Func<TKey,TValue>, int capacity = 128, …) → Memoizer<TKey,TValue> 得到可管理缓存对象
Memoized (this Func<TKey,TValue>, …) → Func<TKey,TValue> 得到替换后的委托(用法最简洁)

IClock(Aore.Toolkit.Resilience,时间源)

成员 签名摘要 说明
IClock.ElapsedMilliseconds long 进程内单调递增毫秒数
SystemClock.Instance static 基于 Stopwatch 的系统时钟单例(不回绕)
ManualClock (long startMilliseconds = 0) / Advance(...) / SetTo(...) 手动推进时钟,用于确定性测试(时间不可倒流)

Timing(Aore.Toolkit.Timing,时间与调度)

成员 签名摘要 说明
ValueStopwatch.StartNew / CreateStopped static → ValueStopwatch struct 零分配计时器;复制即独立快照
ValueStopwatch Start / Stop / Restart / Reset / IsRunning 暂停累计 / 幂等;Restart 全 TFM 可用(ns2.0 补齐)
ValueStopwatch 读数 ElapsedNanoseconds / ElapsedMicroseconds / ElapsedMilliseconds / Elapsed / ElapsedTicks 纳秒级整数读数(分段换算防溢出);毫秒为截断语义
ValueStopwatch.Lap / CreateSnapshot () → TimeSpan / → StopwatchSnapshot 计圈(不重置总累计)/ 只读快照
Monotonic.GetTimestamp / GetElapsedTime () → long / (start[, end]) → TimeSpan 单调时间戳与耗时回传(.NET 7+ API 下放全 TFM)
Monotonic.TimestampToNanoseconds / NanosecondsToTicks (long) → long 刻度 ↔ 纳秒(「整秒 + 余数」分段换算,无中间溢出)
Monotonic.Frequency / Resolution / IsHighResolution long / TimeSpan / bool 频率 / 单刻度时长(100ns 粒度量化)/ 高分辨率感知
Monotonic.Measure / MeasureAsync (Action) → TimeSpan / (Func<Task>) → Task<TimeSpan> 同步 / 异步作用域测量
MonotonicDeadline.FromNow static (TimeSpan budget) → MonotonicDeadline 单调截止预算(readonly struct,可共享)
MonotonicDeadline IsExpired / Remaining / RemainingMilliseconds / ThrowIfExpired() 到期判定;剩余归零不取负;到期抛 TimeoutException
ScheduleMode enum { FixedDelay, FixedRate } FixedDelay 防重叠;FixedRate 防漂移(错过节拍跳过不补发)
ScheduleTimer 构造 (Func<CancellationToken,Task> / (Action, TimeSpan interval, ScheduleMode, ScheduleOptions?) 构造即启动;回调永不重叠;异常交给 OnError 绝不击穿进程
ScheduleTimer.ScheduleOnce static (Action, TimeSpan dueIn, Action<Exception>?) → ScheduleTimer 一次性延迟执行,完成后自动停止
ScheduleTimer 控制 Pause() / Resume() / Dispose() 暂停保留节拍基准;Dispose 幂等不抛并取消在途回调令牌
ScheduleTimer 诊断 ExecutionCount / ErrorCount / SkippedCount / IsRunning / IsPaused Interlocked 计数
ScheduleTimer.WaitForNextTickAsync (CancellationToken = default) → Task<bool> PeriodicTimer 风格 awaitable(全 TFM);Dispose 后返回 false
ScheduleOptions MaxExecutions(0=无限) / OnError / OnCompleted / Name 配置对象(创建后勿改)

IRateLimiter(Aore.Toolkit.Resilience,限流机制)

成员 签名摘要 说明
RateLimiterAlgorithm enum { TokenBucket, FixedWindow, SlidingWindow, Concurrency } 算法枚举
TryAcquire (int permits = 1) → bool 尝试获取;限流失败只返回 false,绝不抛限流异常
WaitTimeFor (int permits = 1) → TimeSpan Zero = 当前可获得,否则为建议等待时长
Acquire (int permits = 1, TimeSpan? timeout = null) / (TimeSpan? timeout) 阻塞等待;超时抛 TimeoutException
WaitAsync (int permits = 1, CancellationToken = default) → Task<bool> 异步等待
TotalAcquired / TotalRejected long 累计放行 / 拒绝(Reset() 不清零)
Reset () → void 重置限流状态
Release(仅并发限制) (int permits = 1) → void 归还并发许可(多还钳 0,不抛异常)
RateLimitOptions Algorithm / Permits / Window / Clock 配置对象
RateLimiterFactory.Create (RateLimitOptions) → IRateLimiter / (algorithm, permits, window, clock?) 按算法创建
TokenBucketRateLimiter (int capacity, double permitsPerSecond, IClock? = null) 令牌桶,允许突发;AvailableTokens 可查余额
FixedWindowRateLimiter (int limit, TimeSpan window, IClock? = null) 固定窗口,开销最小;边界可 2 倍突发
SlidingWindowRateLimiter (int limit, TimeSpan window, IClock? = null) 滑动窗口精确计数,边界平滑;CurrentCount 可查在窗数
ConcurrencyRateLimiter (int maxConcurrency, IClock? = null) 并发在途上限;需配对 Release;Current 可查在途数

CircuitBreaker(Aore.Toolkit.Resilience,熔断器模式)

成员 签名摘要 说明
CircuitState enum { Closed, Open, HalfOpen } 三态
CircuitBreakerOptions FailureThreshold(5) / BreakDuration(30s) / HalfOpenTrialCount(1) / SuccessThreshold(1) / OnStateChanged 配置;Validate() 校验并返回自身
CircuitBreaker (CircuitBreakerOptions? = null, IClock? = null) 熔断器;不含重试(重试会放大下游压力)
State / Snapshot CircuitState / CircuitBreakerSnapshot 状态(读取不触发迁移,判定以 TryAcquire 为准)/ 指标快照
TryAcquire / ReportSuccess / ReportFailure () → bool / () → void / () → void 手动模式
Execute / ExecuteAsync (Action) / (Func<T>) → T / (Func<Task>) / (Func<Task<T>>) → Task<T> 自动模式;熔断打开时抛 CircuitOpenException
Reset () → void 强制闭合并清零全部计数
CircuitOpenException (string, CircuitState, TimeSpan? retryAfter) 快速失败异常(继承 Exception,携带 State / RetryAfter)
CircuitBreakerSnapshot State / TimeInCurrentState / TotalCalls / TotalSuccesses / TotalFailures / ConsecutiveFailures / ConsecutiveSuccesses / RejectedCalls / RetryAfter 只读结构体快照
CircuitBreakerRegistry Get(name) / TryGet / All / Count / ResetAll / Remove(name) / Clear() / MaxBreakers 按下游隔离状态;同名恒同一实例;Remove / Clear 手动回收条目;MaxBreakers 容量软上限(超限按创建序只淘汰 Closed 态,默认 0 = 不限制)

集合选型速查

需求 选择
高频耗时统计(零分配、亚毫秒精度) ValueStopwatch(struct)
跨 await 的超时预算检查 MonotonicDeadline
时间戳差值 / 高精度换算 / 作用域测量 Monotonic.GetElapsedTime / Measure
周期任务防重叠(回调耗时不定) ScheduleTimer(FixedDelay)
周期任务防漂移(错过节拍跳过不补发) ScheduleTimer(FixedRate)
一次性延迟执行 ScheduleTimer.ScheduleOnce
任意位置 O(1) 插入删除 + 持有节点引用(LRU / 撤销栈) DoublyLinkedList<T>
两端插入删除 Deque<T>(或 Queue<T> + 本库扩展)
栈内最值 MinMaxStack<T>
只有 IList<T> 接口、需要批量 / 原地操作 ListExtensions
高频事件合并(输入联想 / 自动保存) Debouncer
高频事件限速(滚动 / 鼠标移动) Throttle
昂贵函数结果复用 Memoizer<TKey, TValue>(按 key)或 MemoizeOnce(无参)
限制下游请求速率(允许突发) TokenBucketRateLimiter
平滑限速 / 计数最简 SlidingWindowRateLimiter / FixedWindowRateLimiter
限制同时在途请求数 ConcurrencyRateLimiter
下游故障时快速失败 CircuitBreaker(可经 CircuitBreakerRegistry 按下游隔离)

API 完整使用方法

ObjectPool(通用对象池)

// 1) 内置 StringBuilder 池(归还时自动 Clear)
var sb = ObjectPool.StringBuilderPool.Rent();
try
{
  sb.Append("Aore.Toolkit");
}
finally
{
  ObjectPool.StringBuilderPool.Return(sb);
}

// 2) 自定义池:工厂 + 复位回调 + 容量上限 + 预热
var pool = new ObjectPool<List<string>>(
  () => new List<string>(16),                 // 工厂
  list => list.Clear(),                        // 复位回调
  maxRetained: 64,
  preRent: 8);                                 // 预热 8 个(受 maxRetained 约束)

var list = pool.Rent();
list.Add("x");
pool.Return(list);                             // 复位后入池

// 3) 全局共享池:同一 T 只有一个池实例
var shared = ObjectPool.For<MemoryStream>();
ObjectPool.ClearSharedPools();                 // 内存压力回落 / 测试隔离

ReflectionCache(带缓存反射)

// 元数据查找(命中后不再触发反射)
var prop = ReflectionCache.GetProperty(typeof(User), nameof(User.Name));   // 不存在返回 null
var method = ReflectionCache.GetMethod(typeof(User), nameof(User.Save), new[] { typeof(string) });
var element = ReflectionCache.GetElementType(typeof(List<int>));          // int
ReflectionCache.GetDefaultValue(typeof(DateTime));                        // 0001-01-01

// 缓存的读写委托(表达式树编译,命中后接近字段访问速度)
var getter = ReflectionCache.GetPropertyGetter(typeof(User), nameof(User.Name));
var setter = ReflectionCache.GetPropertySetter(typeof(User), nameof(User.Name));
var user = new User();
setter!(user, "Aore");
string? name = (string?)getter(user);

// 链式扩展方法形态
user.SetPropertyValue(nameof(User.Name), "Willis");
var value = user.GetPropertyValue(nameof(User.Name));

// 只读属性 / 缺失成员
ReflectionCache.GetPropertySetter(typeof(User), nameof(User.Id));         // null(只读)
ReflectionCache.GetPropertyGetter(typeof(User), "NotExist");              // 抛 MissingMemberException

ReflectionCache.Clear();                                                  // 清空进程级缓存

// 插件卸载 / Collectible ALC:按类型精准清除,防止程序集被缓存条目钉住
ReflectionCache.Clear(typeof(User));

// 可选:启用条目总数预警水位(软上限,越线按 Type FIFO 自动驱逐最旧类型;默认 0 = 关闭)
ReflectionCache.HighWaterMark = 50_000;

单例

// 继承式单例基类(推荐:可加初始化钩子与释放逻辑)
public sealed class AppConfig : SingletonBase<AppConfig>
{
  public string Endpoint { get; private set; } = "https://default";

  protected override void OnSingletonCreated() => Endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? Endpoint;
}

var config = AppConfig.Instance;

// 普通泛型单例(无需继承)
var helper = Singleton<JsonHelper>.Instance;

Iterator / EnumerableIterator(迭代器)

// 惰性序列
Iterator.Empty<int>();                                // 空序列(零分配共享单例)
Iterator.Repeat("A", 3);                              // A A A
Iterator.RepeatSequence(new[] { 1, 2 }, 2);           // 1 2 1 2
Iterator.Range(1, 3);                                 // 1 2 3
Iterator.Range(10, 0, -2);                            // 10 8 6
Iterator.Range(0, 10, -1);                            // 空(方向不匹配,不死循环)
Iterator.Range(int.MaxValue, 2);                      // 抛 ArgumentOutOfRangeException

Iterator.Batch(new[] { 1, 2, 3, 4, 5 }, 2);           // [1,2] [3,4] [5]
Iterator.Window(new[] { 1, 2, 3 }, 2);                // [1,2] [2,3]

// 无限序列需自行截断
Iterator.Repeat(1).Take(3);                           // 1 1 1
Iterator.Cycle(new[] { 1, 2 }).Take(3);               // 1 2 1

// 迭代器模式游标:HasNext 不推进位置
var cursor = Iterator.Create(new[] { 1, 2, 3 });
cursor.HasNext;                                       // true(位置仍为 0)
while (cursor.MoveNext())
{
  var item = cursor.Current;
}
cursor.Position;                                      // 3
cursor.Reset();                                       // 可重复遍历

// 游标同时是 IEnumerable<T>,可直接接 LINQ
var even = ((EnumerableIterator<int>)Iterator.Create(Enumerable.Range(1, 5))).Where(x => x % 2 == 0);

DoublyLinkedList(双向链表)

using Aore.Toolkit.Collections;

// 头尾插入,节点可被外部持有
var list = new DoublyLinkedList<string>();
var node = list.AddLast("B");
list.AddFirst("A");
list.AddAfter(node, "C");              // A, B, C
list[node] = "BB";                      // 按节点读写:A, BB, C

// 任意位置 O(1) 移动(保持同一节点实例,外部引用不失效)
list.MoveToFirst(node);                // BB, A, C
list.MoveBefore(node, list.Last!);      // A, BB, C

// 遍历(含反向)
list.ForEach(x => Console.WriteLine(x));
list.ForEachBackward(x => Console.WriteLine(x));   // C, BB, A

// 节点移出后导航清空,避免悬挂引用
list.Remove(node);
Console.WriteLine(node.List);          // null
Console.WriteLine(node.Previous);      // null

LRU 缓存(双向链表 + 字典,两行核心逻辑)

var order = new DoublyLinkedList<string>();      // 最近使用在前
var store = new Dictionary<string, byte>();

void Touch(string key)
{
  if (store.ContainsKey(key))
  {
    order.MoveToFront(key);                       // 命中 → 提到最前
  }
  else
  {
    store[key] = 0;
    order.MoveToBack(key);                        // 新增 → 放到最后(最旧)

    if (order.Count > 3)                          // 超容量 → 淘汰最旧
    {
      var oldest = order.Last!.Value;
      order.RemoveLast();
      store.Remove(oldest);
    }
  }
}

ListExtensions(列表操作与扩展)

IList<int> numbers = new List<int> { 5, 3, 8, 1, 9, 2 };

numbers.RemoveWhere(x => x < 3);           // 5, 8, 9, 2(返回删除数)
numbers.Swap(0, numbers.Count - 1);        // 2, 8, 9, 5
numbers.ReverseInPlace();                  // 5, 9, 8, 2
numbers.InsertRange(0, new[] { 0 });       // 0, 5, 9, 8, 2
numbers.ReplaceRange(1, new[] { 7, 8 });   // 0, 7, 8, 8, 2
numbers.Fill(-1, 1, 2);                    // 0, -1, -1, 8, 2

var blocks = numbers.Chunk(2);             // 惰性分块
numbers.ShuffleInPlace(new Random(42));    // 原地洗牌(Fisher-Yates)
var sorted = numbers.Shuffled().OrderBy(x => x);

numbers.At(99);                            // 越界安全取值 → default(T) = 0
numbers.IsInRange(0);                      // true
numbers.TryEnsureCapacity(1024);           // List<T> 专用,返回是否扩容

var sortedList = new List<int> { 1, 3, 5, 7 };
sortedList.BinarySearchIndex(5);           // 2(命中)
sortedList.BinarySearchIndex(6);           // 负数(~插入点)

QueueExtensions / Deque(队列工具)

var queue = new Queue<int>();
queue.EnqueueRange(new[] { 1, 2, 3, 4 });  // 批量入队
queue.DequeueWhile(x => x < 3);            // 出队 1, 2(返回 2),剩余 3, 4
queue.DequeueRange(10);                    // 取尽 → [3, 4]
queue.DequeueAll();                        // []

// 双端队列
var deque = new Deque<string>();
deque.PushBack("B");
deque.PushFront("A");
deque.PushBack("C");
deque.PeekFront();                        // A
deque.PopBack();                          // C
deque.TryPopBack(out var tail);           // B → true(空时返回 false)

StackExtensions / MinMaxStack(堆栈工具)

var stack = new Stack<int>();
stack.PushRange(new[] { 1, 2, 3 });       // 栈顶为 3
stack.PopWhile(x => x > 2);               // 弹出 3(返回 1)
stack.TryPop(out var top);                // 2 → true

// O(1) 最值栈(滑动窗口最值场景)
var window = new MinMaxStack<int>();
foreach (var v in new[] { 4, 2, 9, 6 })
{
  window.Push(v);
}

window.GetMin();                          // 2
window.GetMax();                          // 9
window.Pop();
window.GetMax();                          // 6(自动回退)

// 自定义比较器(降序)
var desc = new MinMaxStack<int>(Comparer<int>.Create((x, y) => y.CompareTo(x)));

FuncExtensions(函数处理)

using Aore.Toolkit.Functions;

// 安全调用:捕获可恢复异常,OutOfMemory 等致命异常仍会抛出
if (!((Action)DoWork).TryInvoke(out var error))
{
  Console.WriteLine(error!.Message);
}

// 事件回调:异常交给处理器,不向外抛
((Action)DoWork).InvokeSafely(ex => Console.WriteLine(ex.Message));

// 兜底取值 / 条件调用
Func<int> parse = () => throw new FormatException("bad");
int value = parse.InvokeOrDefault(-1);
parse.InvokeIf(false, -1);            // -1(不执行 parse)

// 超时调用:超时抛 TimeoutException(返回值版本返回兜底值)
((Func<int>)SlowCall).InvokeWithTimeout(TimeSpan.FromSeconds(2), fallback: -1);

// 同步重试:第 3 次成功;耗尽后重抛最后一次异常
Func<string> call = () => RemoteGet();
var body = call.Retry(maxAttempts: 3, delay: TimeSpan.FromMilliseconds(200));

// 自定义重试条件:不可恢复的错误立即抛出
call.Retry(maxAttempts: 5, shouldRetry: ex => ex is TimeoutException);

// 异步重试(支持取消)
await ((Func<Task<string>>)RemoteGetAsync).RetryAsync(maxAttempts: 3, cancellationToken: ct);

// 函数组合
Func<string, string> mark = s => s + "?";
Func<string, int> length = s => s.Length;
Func<string, int> composed = mark.Compose(length);   // s => (s + "?").Length

// 无参工厂的单键记忆化(异常也会被缓存)
var loadConfig = ((Func<string>)ReadConfigFile).MemoizeOnce();

Debouncer(防抖)

// 搜索框:连续输入只在停止 300ms 后请求一次
string keyword = string.Empty;
using var debouncer = new Debouncer(() => Search(keyword), TimeSpan.FromMilliseconds(300));

keyword = "aore"; debouncer.Invoke();
keyword = "aore t"; debouncer.Invoke();   // 计时被重置
// ... 300ms 后 Search 只被调用一次,keyword 已是最终值

debouncer.IsPending;   // 是否有待执行动作
debouncer.Flush();      // 立即执行(返回 true),并取消后续定时触发
debouncer.Cancel();     // 放弃本次防抖

Throttle(节流)

// 滚动加载:100ms 内最多触发一次
int offset = 0;
using var throttle = new Throttle(() => LoadMore(offset), TimeSpan.FromMilliseconds(100));

throttle.Invoke();   // true(首次前导执行)
throttle.Invoke();   // false(窗口内被丢弃)
throttle.Invoke();   // false

// 后置模式:窗口结束才执行,适合埋点 / 自动保存
using var saver = new Throttle(() => Save(), TimeSpan.FromMilliseconds(500), ThrottleMode.Trailing);
saver.Invoke();      // false(不立即执行)
// 500ms 内多次调用只会在窗口结束时执行一次

Memoizer(函数缓存 / 记忆化)

// 得到可管理的缓存对象:查看命中率、失效、清空
Func<string, Type> resolve = name => AssemblyScan(name);
var cache = resolve.Memoize(capacity: 256);

cache.Get("User"); cache.Get("User");
Console.WriteLine(cache.HitRate);        // 0.5
cache.Invalidate("User");               // 强制下次重算
cache.Clear();

// 简洁用法:直接拿到替换后的委托
Func<string, Type> cachedResolve = resolve.Memoized(capacity: 256);

// 自定义比较器(大小写不敏感)
var insensitive = resolve.Memoize(capacity: 256, StringComparer.OrdinalIgnoreCase);

// 带有效期:惰性过期(访问时判定,无后台线程);ttlSelector 可按 key / 值定制每项有效期
var expiring = resolve.Memoize(capacity: 256, ttl: TimeSpan.FromMinutes(5));
var perKey = resolve.Memoize(capacity: 256, ttlSelector: (key, _) => key.StartsWith("temp:") ? TimeSpan.FromSeconds(30) : TimeSpan.FromMinutes(10));

IClock(时间源,可确定性测试)

using Aore.Toolkit.Resilience;

// 系统时钟(默认)
IClock clock = SystemClock.Instance;

// 手动时钟:让所有「等一段时间」的场景变成纯逻辑断言,零 sleep、零偶发
var fake = new ManualClock();
var limiter = new FixedWindowRateLimiter(limit: 2, window: TimeSpan.FromSeconds(1), fake);
limiter.TryAcquire();
limiter.TryAcquire();
limiter.TryAcquire();      // false

fake.Advance(TimeSpan.FromSeconds(1));
limiter.TryAcquire();      // true(窗口已重置)

时间与调度(高精度计时 / 单调预算 / 调度定时器)

using Aore.Toolkit.Timing;

// 高精度计时器(struct 零分配,复制即独立快照):亚毫秒整数读数 + 全 TFM 可用的 Restart
var stopwatch = ValueStopwatch.StartNew();
DoWork();
stopwatch.Stop();
Console.WriteLine($"{stopwatch.ElapsedMilliseconds}ms / {stopwatch.ElapsedMicroseconds}µs");
stopwatch.Restart();                                    // 清零重新走表(ns2.0 也有)

// 时间戳差值与作用域测量(.NET 7+ GetElapsedTime 下放全 TFM)
var start = Monotonic.GetTimestamp();
await Task.Delay(100);
var elapsed = Monotonic.GetElapsedTime(start);
var measured = Monotonic.Measure(() => Thread.Sleep(50));   // 一行测耗时

// 单调截止预算:跨多次 await 的超时检查(与 CancellationTokenSource 墙钟超时互补)
var deadline = MonotonicDeadline.FromNow(TimeSpan.FromSeconds(5));
foreach (var item in items)
{
    deadline.ThrowIfExpired();                              // 到期抛 TimeoutException
    await ProcessAsync(item);
}

// 调度定时器:回调永不重叠、异常不击穿进程、支持异步回调
using var timer = new ScheduleTimer(
    async token => await HeartbeatAsync(token),
    TimeSpan.FromSeconds(10),                               // FixedDelay:上次完成后隔 10s 再跑
    options: new ScheduleOptions { Name = "heartbeat", OnError = ex => Log(ex) });

// 固定速率防漂移:错过节拍跳过不补发(SkippedCount 累计)
using var meter = new ScheduleTimer(PollAsync, TimeSpan.FromMilliseconds(250), ScheduleMode.FixedRate);

// 一次性延迟执行
var once = ScheduleTimer.ScheduleOnce(() => Console.WriteLine("40ms 后"), TimeSpan.FromMilliseconds(40));

// PeriodicTimer 风格的 awaitable 接口(全 TFM 可用)
while (await timer.WaitForNextTickAsync(cancellationToken))
{
    await HandleTickAsync();
}

限流(4 种算法)

// 令牌桶:允许 capacity 突发,长期按 permitsPerSecond 均速
var bucket = new TokenBucketRateLimiter(capacity: 100, permitsPerSecond: 50);
if (!bucket.TryAcquire())
{
  // 降级:返回缓存 / 排队 / 提示稍后重试
}
var wait = bucket.WaitTimeFor();      // 建议等待时长(Zero = 当前可获得)

// 固定窗口:开销最小,窗口边界可 2 倍突发
var fixedWindow = new FixedWindowRateLimiter(limit: 100, window: TimeSpan.FromSeconds(1));

// 滑动窗口:精确计数,边界平滑;内存 O(limit)
var sliding = new SlidingWindowRateLimiter(limit: 100, window: TimeSpan.FromSeconds(1));

// 并发限制:限制同时在途请求数
var slots = new ConcurrencyRateLimiter(maxConcurrency: 8);
if (slots.TryAcquire())
{
  try
  {
    CallDownstream();
  }
  finally
  {
    slots.Release();     // 必须配对归还
  }
}

// 阻塞 / 异步等待
bucket.Acquire(timeout: TimeSpan.FromSeconds(2));       // 超时抛 TimeoutException
await bucket.WaitAsync(cancellationToken: ct);          // 异步等待

// 按配置统一创建
IRateLimiter limiter = RateLimiterFactory.Create(new RateLimitOptions
{
  Algorithm = RateLimiterAlgorithm.TokenBucket,
  Permits = 100,
  Window = TimeSpan.FromSeconds(1),
});

熔断器(快速失败)

using Aore.Toolkit.Resilience;

var breaker = new CircuitBreaker(new CircuitBreakerOptions
{
  FailureThreshold = 5,                       // 连续 5 次失败后打开
  BreakDuration = TimeSpan.FromSeconds(30),   // 打开持续 30s
  HalfOpenTrialCount = 2,                     // 半开放行 2 个试探
  SuccessThreshold = 2,                       // 成功 2 次后闭合
  OnStateChanged = state => Metrics.Track("circuit", state),   // 锁内同步,别做耗时操作
});

try
{
  var user = breaker.Execute(() => UserService.Get(1));        // 自动上报
}
catch (CircuitOpenException ex)
{
  // ex.State / ex.RetryAfter 告诉你「现在别打,稍后再来」
  return Fallback();
}
catch (HttpRequestException ex)
{
  // 业务异常原样透传,已计入失败
}

// 异步版:取消(OperationCanceledException)不计入失败
var user = await breaker.ExecuteAsync(() => UserService.GetAsync(1));

// 手动模式(自定义判定逻辑)
if (breaker.TryAcquire())
{
  try
  {
    DoWork();
    breaker.ReportSuccess();
  }
  catch
  {
    breaker.ReportFailure();
    throw;
  }
}

// 指标快照
var snap = breaker.Snapshot;
Console.WriteLine($"{snap.State} calls={snap.TotalCalls} fails={snap.TotalFailures} rejected={snap.RejectedCalls}");

// 按下游隔离状态
var registry = new CircuitBreakerRegistry(new CircuitBreakerOptions { FailureThreshold = 2 });
registry.Get("user-service").Execute(() => CallUserService());
registry.Get("order-service").Execute(() => CallOrderService());

// 容量软上限:超限按创建序只淘汰 Closed 态(Open / HalfOpen 与本次新建绝不淘汰);下游下线可手动移除
var bounded = new CircuitBreakerRegistry(new CircuitBreakerOptions { FailureThreshold = 2 }, maxBreakers: 32);
bounded.Remove("offline-service");

注意事项

  1. null 约定:本库不提供公共参数校验与字符串扩展工具(模板示例模块已移除)。参数校验请直接使用 ArgumentNullException.ThrowIfNull(net6+)或手写 if (x is null) throw new ArgumentNullException(nameof(x));;字符串判空请用 string.IsNullOrWhiteSpace。本库各方法的 null 语义差异(null 安全 / 要求非 null)均在 XML 注释标注。

  2. 异常约定:公共 API 优先抛标准异常(ArgumentNullException / ArgumentException / ArgumentOutOfRangeException / MissingMemberException / AmbiguousMatchException / TimeoutException / InvalidOperationException),并尽量携带 paramName;唯一专用异常是熔断快速失败的 CircuitOpenException(携带 State / RetryAfter)。

  3. 对象池不释放实例:Trim / Clear 只丢弃不调用 IDisposable.Dispose,池不擅自释放以避免二次释放;需要清理请放在复位回调中。

  4. 对象池容量:maxRetained = 0 表示关闭池化(每次都新建);preRent 会被 maxRetained 截断。命中率 = 1 - CreatedCount / 租用总次数。

  5. 反射缓存是进程级共享:ReflectionCache.Clear() 供动态程序集卸载 / 插件热重载 / 测试隔离使用;缓存持有 Type 引用,请勿在卸载场景下依赖默认行为。

  6. 反射方法查找范围:GetMethod 依赖 Type.GetMethods 语义,可查到继承的 public / protected 方法,但不包含基类的 private 方法;属性与字段查找则显式遍历基类全链。

  7. Aore.Toolkit.Reflection 命名空间与 System.Reflection 同名段:在该命名空间内请统一写 using System.Reflection; 并使用 Type / MethodInfo 等裸类型名,不要写 Reflection.Xxx。

  8. 单例 Reset() 仅供测试:SingletonBase<T>.Reset() / Singleton<T>.Reset() 会破坏单例语义(外部可能仍持有旧实例),生产代码禁止调用;释放资源请用 DisposeInstance()。

  9. 无限序列:Iterator.Repeat(value) 与 Iterator.Cycle(source) 返回无限序列,必须自行截断(例如 Take(n)),否则 foreach 不会结束。

  10. 游标线程安全:EnumerableIterator<T> 与 BCL 枚举器一致,非线程安全,请勿跨线程共享。

  11. 集合容器线程安全:DoublyLinkedList<T> / Deque<T> / MinMaxStack<T> 均非线程安全(与 BCL 集合一致),需要并发安全请由调用方加锁。

  12. 扩展方法同名遮蔽:部分扩展方法在 net6+ 会被同名 BCL 实例方法遮蔽(实例方法优先)——GetRange / InsertRange / TryPop 等。库内已对齐语义与异常类型;调用方若需明确指定,请用静态调用形式(如 ListExtensions.TryPop(stack, out var v))。

  13. 反向/原地语义:ReverseInPlace / ShuffleInPlace / Shuffled(前者就地修改,后者返回副本)。

  14. 超时不能中止:InvokeWithTimeout 只保证「调用方不再等待」,已启动的工作会继续在后台运行(异常会被观察,不会触发 UnobservedTaskException)。需要真正中止请自行传入 CancellationToken。

  15. 定时器必须释放:Debouncer / Throttle 的 Timer 懒建但生命周期跟随实例,请用 using / Dispose() 释放;动作异常<b>默认被吞</b>,强烈建议传 onError 回调。

  16. 记忆化与防抖的适用边界:MemoizeOnce 只适用于无参工厂(带参数请用 Memoize / Memoized);Memoizer 并发同 key 允许重复计算,工厂应无副作用;Retry 的 Thread.Sleep 会阻塞调用线程,长耗时场景请用 RetryAsync。

  17. 目标框架:所有 API 在 7 个 TFM 上行为一致;垫片(Compatibility/NullableAttributes.cs)保证旧框架下的可空注解编译,无运行时开销。net462 不内置 ValueTuple,本库缓存键使用自定义结构体以保持零依赖。

  18. 限流只返回 false:TryAcquire 被拒时不抛异常(避免异常风暴);只有 Acquire 在超时后才抛 TimeoutException。permits 大于限流器配额属配置错误,会一直拿不到许可。

  19. 熔断器不含重试:CircuitBreaker.Execute* 不内置重试——熔断期间重试只会放大下游压力。重试用 FuncExtensions.Retry* 组合,且只对「非 CircuitOpenException」重试。

  20. 熔断状态是惰性迁移:State 读取本身不触发迁移,Open → HalfOpen 的迁移发生在 TryAcquire 中,因此判定权威入口是 TryAcquire。

  21. 时间行为可测:限流与熔断的全部时间判定走 IClock,传入 ManualClock 即可在零 sleep的前提下确定性验证(库自身的测试即如此)。

  22. 仅单进程生效:限流与熔断都是进程内状态,集群下每个实例各限各的;分布式场景需外部存储(属非目标)。

  23. 线程安全:无状态静态工具(Iterator / ReflectionCache / FuncExtensions)天然线程安全;ObjectPool 加锁、SingletonBase 用 Lazy<T>、Debouncer / Throttle / Memoizer / 全部限流器 / CircuitBreaker / CircuitBreakerRegistry 均为线程安全实现;集合容器与游标除外(见第 10 / 11 条)。

  24. 内部类型不是公共 API:Aore.Toolkit.Internal 命名空间下的类型(如参数守卫)属实现细节,随版本可变更,不保证向后兼容。

  25. 重试不重试取消异常:Retry / Retry<T> / RetryAsync / RetryAsync<T> 遇到 OperationCanceledException(含 TaskCanceledException)立即原样抛出,不消耗剩余重试次数;需重试取消场景请自行在 shouldRetry 之外处理。

  26. 熔断中的取消不计成功也不计失败:CircuitBreaker.ExecuteAsync* 遇到 OperationCanceledException 只清零连续失败并原样抛出,不会被记为下游成功(避免 InvokeWithTimeout 产生的超时把熔断计数清零)。

  27. Acquire 的超时是真实墙钟:IRateLimiter.Acquire(permits, timeout) 的 timeout 由内部 Stopwatch 判定,不受注入的 IClock 影响(否则传入 ManualClock 会永不超时);单次等待时长仍由 IClock 决定。

  28. 限流请求量不得超过配额:SlidingWindowRateLimiter 的 WaitTimeFor(permits > Limit) / Acquire 会抛 ArgumentOutOfRangeException(该请求量本质不可满足,快速失败而非空转);其余限流器 TryAcquire 一律返回 false 不抛异常。

  29. CircuitBreaker.Execute 重载选择:() => Foo() 这类有返回值的表达式体 lambda 会按 C# 规则绑定到 Execute<T> 而非 Execute(Action);需明确执行 Action 版本请写成 Action act = () => Foo();。

  30. 枚举器耗尽安全:全部 struct 枚举器(DoublyLinkedList<T>.Enumerator / Deque<T>.Enumerator / MinMaxStack<T>.Enumerator)在未开始或已越界时 Current 返回 default(T),不抛异常。

  31. ReflectionCache 不适用于裁剪 / NativeAOT:属性 / 字段 / 方法在裁剪后可能被移除,GetProperty 等会返回 null、GetValue 会抛 MissingMemberException;Expression.Compile() 在不支持动态代码的平台已自动降级为反射访问(性能下降但功能正确)。

  32. EnumerableIterator<T> 双重身份:类型同时是游标(IIterator<T>)与序列(IEnumerable<T>)。作为序列枚举(foreach / LINQ)时返回独立新游标,不会重置本实例的 Position / Current。

  33. DoublyLinkedList<T> 自定义比较器:如需非默认比较(如大小写不敏感),用 new DoublyLinkedList<T>(source, comparer);Find / Remove(T) / Contains 均按该比较器判定。

  34. SingletonBase<T>.Dispose() 会重置单例:释放的正是当前单例实例时会原子丢弃缓存引用,下次 Instance 重新构造(等价于 DisposeInstance())。

  35. 缓存键空间由调用方控制:ReflectionCache(按 Type / 成员)、ObjectPool 共享池(按泛型实参)、CircuitBreakerRegistry(按名称)的条目随使用增长,键空间有限时收敛;以动态键(动态生成类型、per-user / per-request 命名)访问会导致条目无限增长。管控选型:手动清理是地基(ReflectionCache.Clear(type) / Registry.Remove(name) / Clear() / ObjectPool.RemoveShared<T>()),容量管控是无人运维场景的兜底(ReflectionCache.HighWaterMark / Registry 的 maxBreakers,均为默认关闭的软上限),TTL 只属于业务值缓存(Memoizer);本库不内置定时清扫线程。

  36. Collectible AssemblyLoadContext 卸载前先清缓存:ReflectionCache 条目持有 Type / MemberInfo / 编译委托引用,只要条目存在,可卸载程序集就被钉住无法卸载。插件卸载前调用 ReflectionCache.Clear(pluginType)(或全量 Clear());被清条目后续访问自动重反射,正确性不受影响。ObjectPool.RemoveShared(type) 可同步退场插件创建的共享池。

  37. 自动管控是软上限且有驱逐语义:HighWaterMark 越线按 Type 插入序 FIFO 驱逐(每 64 次访问摊销检查,被驱逐条目重新反射 + 重编译,一次性性能毛刺);maxBreakers 超限按创建序只淘汰 Closed 态(Open / HalfOpen 与本次新建绝不淘汰,无可淘汰条目时暂时超限,被淘汰熔断器状态丢失、同名重建归零)。

  38. Memoizer TTL 语义:ttl(默认有效期)与 ttlSelector(按 key / 值定制,优先于 ttl)均缺省 = 永不过期(与旧版行为一致);惰性过期无后台线程——访问时按注入 IClock 的单调毫秒判定,过期条目视同不存在并顺带移除,Get 重新计算并计入 Misses;容量压力下优先淘汰已过期条目;有效期必须为正时间跨度,选择器返回非正抛 ArgumentOutOfRangeException;测试注入 ManualClock 可零 sleep 确定性验证。

  39. Timing 的刻度不是 TimeSpan 刻度:Monotonic.GetTimestamp / ValueStopwatch.ElapsedTicks 为 Stopwatch 刻度(平台频率相关),跨度换算必须经由 Monotonic.TimestampToNanoseconds / GetElapsedTime;ValueStopwatch 为 struct——赋值 / 传参即独立快照(非引用共享);Monotonic.Resolution 按 100ns 粒度量化(GHz 级计数器下为 1 tick 下限)。静态门面类名为 Monotonic 而非 Timing(避开与命名空间同名)。

  40. ScheduleTimer 的防重叠与防漂移:FixedDelay 上次回调完成后再计间隔(推荐默认,天然防重叠);FixedRate 按节拍点排程,回调未完成错过节拍时跳过不补发(SkippedCount 累计,补发会造成突发风暴);回调(含 async)永不重叠;异常交给 OnError(缺省吞掉并计 ErrorCount)绝不击穿进程;间隔为亚毫秒时取 1ms 下限;全部节拍判定基于单调毫秒(无 49 天回绕)。Dispose 幂等不抛(与 Debouncer / Throttle 的 ObjectDisposed 语义刻意不同)并取消在途回调令牌。

  41. WaitForNextTickAsync 是多播语义:同一节拍唤醒当前全部等待者;节拍在「回调开始执行」与「跳过节拍」时发生(不以回调完成为准);未等到节拍的调用方不保留历史节拍;Dispose / 达到 MaxExecutions 后返回 false 结束循环。

支持框架:netstandard2.0、net462、net472、net48、net8.0、net9.0、net10.0。

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 is compatible.  net48 is compatible.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.6.2

    • No dependencies.
  • .NETFramework 4.7.2

    • No dependencies.
  • .NETFramework 4.8

    • No dependencies.
  • .NETStandard 2.0

    • No dependencies.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

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.0 109 10/1/2026