Wiaoj.ObjectPool 0.0.1-alpha.32

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

Wiaoj.ObjectPool

A high-performance, thread-safe, and fully asynchronous object pooling library for .NET.

Wiaoj.ObjectPool extends the capabilities of Microsoft.Extensions.ObjectPool by adding true asynchronous support, blocking/bounded pools, factory pattern integration, leak detection, and zero-allocation leasing. It is designed for high-throughput applications where garbage collection pressure must be minimized and resource management is critical.

NuGet License: MIT

🚀 Key Features

  • ⚡ True Async Support: Native IAsyncObjectPool<T> with ValueTask support. Handles asynchronous creation (CreateAsync) and cleanup (TryResetAsync).
  • 🏭 Factory Integration: Seamlessly integrates with IAsyncFactory<T> for complex object creation logic using Dependency Injection.
  • 🛡️ Hybrid Operation Modes:
    • FIFO (Elastic): Lock-free, extremely fast. Creates new objects instantly if the pool is empty.
    • Bounded (Blocking): Uses SemaphoreSlim. Waits asynchronously if the pool limit is reached. Ideal for resource throttling (e.g., DB connections).
  • 🧠 Smart Lifecycle Management: Supports IResettable (Sync) and IAsyncResettable (Async) interfaces for self-managing objects.
  • 🔍 Leak Detection (Debug Only): Automatically detects if a leased object is garbage collected without being returned, pinpointing the exact stack trace of the leak.
  • ✅ Return Validation: Optional validation logic to ensure objects are returned to the pool in a clean/valid state.
  • 📦 Zero-Allocation Leasing: Uses a readonly struct (PooledObject<T>) to manage the lease lifecycle, ensuring 0 heap allocations during Get/Return cycles.

📥 Installation

Install via NuGet Package Manager:

dotnet add package Wiaoj.ObjectPool

⚡ Quick Start (Synchronous)

For simple CPU-bound objects like StringBuilder or List<T>, use the standard synchronous pool.

1. Register in DI

// Program.cs
using Wiaoj.ObjectPool.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Simple registration (uses new T())
builder.Services.AddObjectPool<StringBuilder>();

// Or with custom factory and reset logic via Lambdas
builder.Services.AddObjectPool<List<int>>(
    factory: () => new List<int>(),
    resetter: list => { list.Clear(); return true; }
);

2. Inject and Use

public class StringService(IObjectPool<StringBuilder> pool)
{
    public string BuildMessage()
    {
        // 'using' ensures the object is automatically returned to the pool
        using PooledObject<StringBuilder> lease = pool.Lease();
        
        StringBuilder sb = lease.Item;
        sb.Append("Hello High Performance!");
        
        return sb.ToString();
    }
}

🔥 Advanced Usage (Asynchronous)

This is where Wiaoj.ObjectPool shines. Ideal for database connections, network streams, or any resource where creation/reset is costly and async.

1. Register Async Pool

builder.Services.AddAsyncObjectPool<MyDbConnection>(
    factory: async ct => await MyDbConnection.CreateAsync(ct),
    resetter: async conn => await conn.ResetStateAsync(),
    options => 
    {
        // Wait asynchronously if 50 connections are already in use.
        options.MaximumRetained = 50;
        options.AccessMode = PoolAccessMode.Bounded; 
    }
);

2. Inject and Use

public class DataService(IAsyncObjectPool<MyDbConnection> dbPool)
{
    public async Task ProcessDataAsync()
    {
        // Leases a connection asynchronously. 
        // If pool is 'Bounded' and full, this line awaits until a slot opens.
        // Supports 'await using' for async disposal.
        await using var lease = await dbPool.LeaseAsync();
        
        var connection = lease.Item;
        await connection.ExecuteQueryAsync("SELECT * FROM Users");
    }
}

🧠 Defining Pool Logic: 4 Strategies

Wiaoj.ObjectPool offers flexibility in how you define object creation and cleanup.

1. The "Quick" Way (Lambdas)

Great for simple objects where logic fits in one line.

builder.Services.AddObjectPool<User>(
    factory: () => new User(),
    resetter: user => { user.Name = null; return true; }
);

Best for objects that know how to clean themselves. No external logic required in Program.cs.

Step 1: Implement IResettable (Sync) or IAsyncResettable (Async).

public class SocketClient : IAsyncResettable
{
    public async ValueTask<bool> TryResetAsync()
    {
        await SendResetCommandAsync(); // Async cleanup!
        return true;
    }
}

Step 2: Register

// No factory or resetter needed! 
builder.Services.AddAsyncResettableObjectPool<SocketClient>(); 

3. The "Factory" Way (IAsyncFactory)

Best when object creation is complex and already handled by an IAsyncFactory<T> implementation in your DI container.

// 1. You already have a factory registered
builder.Services.AddSingleton<IAsyncFactory<MyService>, MyServiceFactory>();

// 2. Register the pool (It automatically uses the registered factory!)
builder.Services.AddAsyncObjectPoolFromFactory<MyService>(
    resetter: async svc => await svc.ResetAsync()
);

4. The "Full Control" Way (Custom Policy)

Best for complex dependencies where you need full control over the policy class.

// Register a class implementing IPoolPolicy<T> or IAsyncPoolPolicy<T>
builder.Services.AddAsyncObjectPool(new MyComplexPolicy());

⚙️ Configuration Modes

You can control the pool's behavior via ObjectPoolOptions.AccessMode:

Mode Description Best For
FIFO (Default) Lock-Free / Elastic. If the pool is empty, it immediately creates a new object. It never blocks the thread. CPU-bound objects (StringBuilder, buffers) where latency matters most.
Bounded Throttled / Blocking. If the pool reaches MaximumRetained limit, GetAsync() will await until an object is returned. Limited resources (DB Connections, Throttled API Clients) to prevent system overload.

🛡️ Developer Experience: Safety Nets

These features are active only in DEBUG builds and have zero performance impact in Release.

1. Leak Detection

If you forget to dispose a PooledObject, the library will catch it during Garbage Collection and log a fatal error with the stack trace.

Code with Bug:

var lease = pool.Lease(); // forgot 'using' or 'Dispose()'
// ... variable goes out of scope ...

Output Window:

[WIAOJ.OBJECTPOOLING LEAK DETECTED]
Object 'StringBuilder' leaked! It was collected without Dispose().
Origin:
    at MyApp.Services.MyService.Method() in C:\Projects\MyApp\Service.cs:line 42

2. Return Validation

Ensure "dirty" objects don't pollute your pool.

builder.Services.AddObjectPool<List<string>>(options => 
{
#if DEBUG
    options.OnReturnValidation = obj => 
    {
        var list = (List<string>)obj;
        if (list.Count > 0) throw new InvalidOperationException("List was not cleared!");
    };
#endif
});

📄 License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET 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.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Wiaoj.ObjectPool:

Package Downloads
Tyto

Package Description

Tyto.Context

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.1-alpha.32 51 2/22/2026
0.0.1-alpha.31 46 2/22/2026
0.0.1-alpha.30 49 2/19/2026
0.0.1-alpha.29 44 2/17/2026
0.0.1-alpha.28 401 2/11/2026
0.0.1-alpha.27 69 2/7/2026
0.0.1-alpha.26 46 2/7/2026
0.0.1-alpha.25 46 2/7/2026
0.0.1-alpha.24 49 2/7/2026
0.0.1-alpha.23 48 1/30/2026
0.0.1-alpha.22 243 1/14/2026
0.0.1-alpha.21 51 1/13/2026
0.0.1-alpha.20 55 1/12/2026
0.0.1-alpha.19 53 1/12/2026
0.0.1-alpha.18 57 1/12/2026
0.0.1-alpha.17 59 1/6/2026
0.0.1-alpha.16 55 1/4/2026
0.0.1-alpha.15 54 1/2/2026
0.0.1-alpha.14 140 12/24/2025
0.0.1-alpha.13 719 12/17/2025
Loading failed