NPipeline.Extensions.Nodes
0.16.0
dotnet add package NPipeline.Extensions.Nodes --version 0.16.0
NuGet\Install-Package NPipeline.Extensions.Nodes -Version 0.16.0
<PackageReference Include="NPipeline.Extensions.Nodes" Version="0.16.0" />
<PackageVersion Include="NPipeline.Extensions.Nodes" Version="0.16.0" />
<PackageReference Include="NPipeline.Extensions.Nodes" />
paket add NPipeline.Extensions.Nodes --version 0.16.0
#r "nuget: NPipeline.Extensions.Nodes, 0.16.0"
#:package NPipeline.Extensions.Nodes@0.16.0
#addin nuget:?package=NPipeline.Extensions.Nodes&version=0.16.0
#tool nuget:?package=NPipeline.Extensions.Nodes&version=0.16.0
NPipeline.Extensions.Nodes
A high-performance, dependency-free extension library for NPipeline that provides ready-made, granular nodes for common data processing tasks.
Overview
NPipeline.Extensions.Nodes provides composable, single-responsibility nodes that users can combine to build complex data processing pipelines. The library focuses on:
- Granularity: Each node performs one well-defined operation
- Performance: Zero-allocation hot paths with compiled expressions and ValueTask support
- Type Safety: Strongly-typed APIs using expression-based property selection
- Developer Experience: Fluent API with method chaining and clear error messages
- Dependency-Free: No external dependencies beyond NPipeline core
Installation
dotnet add package NPipeline.Extensions.Nodes
Requirements
- .NET 8.0, 9.0, or 10.0
- NPipeline core package
Quick Start
Using Builder Extension Methods (Recommended)
The simplest way to use nodes is through the fluent builder extension API:
using NPipeline;
using NPipeline.Extensions.Nodes;
var builder = new PipelineBuilder();
// String cleansing with configuration
builder.AddStringCleansing<Customer>(n => n
.Trim(x => x.Name)
.ToLower(x => x.Email));
// Numeric validation with automatic error handling
builder.AddNumericValidation<Order>(n => n
.IsPositive(x => x.Quantity)
.IsBetween(x => x.Discount, 0, 100));
// Collection cleansing
builder.AddCollectionCleansing<User>(n => n
.RemoveNulls(x => x.Tags)
.RemoveDuplicates(x => x.Roles));
// Filtering with predicates
builder.AddFilteringNode<Customer>(n => n
.Where(x => x.Age >= 18)
.Where(x => !string.IsNullOrEmpty(x.Email)));
// Type conversion with custom converter
builder.AddTypeConversion<string, int>(s => int.Parse(s));
// Enrichment with default values
builder.AddEnrichment<Order>(n => n
.DefaultIfNull(x => x.OrderDate, DateTime.UtcNow)
.Compute(x => x.Total, order => order.Quantity * order.UnitPrice));
var pipeline = builder.Build();
Creating Custom Validation Nodes
For domain-specific validation, extend ValidationNode<T>:
using NPipeline.Extensions.Nodes;
public sealed class CustomerValidator : ValidationNode<Customer>
{
public CustomerValidator()
{
Register(c => c.Email, IsValidEmail, "ValidEmail");
Register(c => c.Age, age => age >= 18 && age <= 120, "ValidAge");
Register(c => c.Name, name => !string.IsNullOrWhiteSpace(name), "NotEmpty");
}
private static bool IsValidEmail(string email)
=> !string.IsNullOrWhiteSpace(email) && email.Contains('@');
}
// Use with builder
builder.AddValidationNode<Customer, CustomerValidator>("customer-validation");
Creating Custom Transformation Nodes
For domain-specific transformations, extend PropertyTransformationNode<T>:
using NPipeline.Extensions.Nodes;
public sealed class CustomerNormalizer : PropertyTransformationNode<Customer>
{
public CustomerNormalizer()
{
Register(c => c.Name, name => name?.Trim().ToUpperInvariant());
Register(c => c.Email, email => email?.Trim().ToLowerInvariant());
Register(c => c.Phone, phone => phone?.Replace("-", "").Replace(" ", ""));
}
}
// Use with builder
builder.AddTransform(new CustomerNormalizer(), "normalize-customer");
Architecture Highlights
Zero-Allocation Hot Paths
All nodes override ExecuteValueTaskAsync to return ValueTask<T> directly, avoiding Task<T> allocations on successful synchronous execution:
protected internal override ValueTask<T> ExecuteValueTaskAsync(T item, PipelineContext context, CancellationToken cancellationToken)
{
// Process item
return new ValueTask<T>(item); // No Task allocation!
}
Compiled Property Access
Property selectors are compiled once at configuration time, with no reflection in the execution path:
// This expression:
Register(c => c.Email, email => email?.Length > 0, "NotEmpty");
// Results in pre-compiled delegates that execute in O(1) time
var accessor = PropertyAccessor.Create(selector);
Thread Safety
All nodes are stateless and thread-safe by design:
- Predicates and transformations are pure functions
- No shared mutable state
- Safe for concurrent execution across multiple threads
License
MIT License - see LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 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. |
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 |
|---|---|---|
| 0.16.0 | 28 | 2/24/2026 |
| 0.15.0 | 49 | 2/19/2026 |
| 0.14.0 | 85 | 2/17/2026 |
| 0.13.1 | 80 | 2/13/2026 |
| 0.13.0 | 80 | 2/13/2026 |
| 0.12.0 | 87 | 2/9/2026 |
| 0.11.0 | 87 | 2/8/2026 |
| 0.10.0 | 87 | 2/6/2026 |
| 0.9.1 | 86 | 2/5/2026 |
| 0.9.0 | 86 | 2/5/2026 |
| 0.8.0 | 87 | 2/3/2026 |
| 0.7.1 | 91 | 2/1/2026 |
| 0.7.0 | 89 | 1/31/2026 |
| 0.6.6 | 88 | 1/21/2026 |
| 0.6.5 | 93 | 1/19/2026 |
| 0.6.4 | 93 | 1/18/2026 |
| 0.6.3 | 88 | 1/14/2026 |
| 0.6.2 | 85 | 1/13/2026 |
| 0.6.1 | 98 | 1/13/2026 |