A collection of lightweight extension libraries for .NET. Each library ships as its own NuGet package so you only take what you need.
| Package | Description |
|---|---|
Spirantis.Extensions.System |
Extension methods for common System types — date/time conversions, span-aware string trimming, and reflection-based type discovery. |
Spirantis.Extensions.Threading |
Asynchronous coordination primitives — FIFO-ordered async locking and serial execution of async work, globally or partitioned per key. |
Spirantis.Extensions.Configuration |
Composable application configuration — pluggable source agents layered over environment variables and command-line arguments. |
Spirantis.Extensions.Configuration.Source.Json |
Machine-wide and service-local JSON file configuration sources. |
Spirantis.Extensions.Configuration.Source.AWSParameterStore |
AWS Systems Manager Parameter Store configuration source with recursive loading and JSON flattening. |
Spirantis.Extensions.Logging |
Serilog-based application logging — host integration, config-driven levels, a pluggable sink model, and structured event/REST helpers. |
Spirantis.Extensions.Logging.Sink.Console |
Themed text and structured JSON console logging sinks. |
Spirantis.Extensions.Logging.Sink.File |
Asynchronous rolling-file logging sink. |
Spirantis.Extensions.Logging.Sink.AWSCloudWatch |
AWS CloudWatch Logs sink. |
Spirantis.Extensions.Logging.Sink.Syslog |
Local syslog (RFC 5424) sink, Linux only. |
Spirantis.Extensions.DependencyInjection.Autofac |
Autofac helpers — named IOptions<T> registration and per-constructor-parameter named resolution. |
Spirantis.Extensions.Hosting |
Priority-ordered hosted services (Superior/Normal/Inferior tiers), container-agnostic. |
Spirantis.Extensions.Hosting.Autofac |
Autofac registration glue for the arrangeable hosted services. |
All packages target .NET 10 and are MIT licensed. The System and Threading
packages are dependency-free; the Configuration packages build on
Microsoft.Extensions.Configuration (and the AWS SDK, for the Parameter Store source).
Spirantis.Extensions.slnx # solution tying everything together
src/
.editorconfig # shared code style
Directory.Build.props # shared package metadata
Spirantis.Extensions.System/ # library + its package README
Spirantis.Extensions.System.Tests/
Spirantis.Extensions.Threading/ # library + its package README
Spirantis.Extensions.Threading.Tests/
Spirantis.Extensions.Configuration/ # core configuration library
Spirantis.Extensions.Configuration.Tests/
Spirantis.Extensions.Configuration.Source.Json/ # JSON file sources
Spirantis.Extensions.Configuration.Source.Json.Tests/
Spirantis.Extensions.Configuration.Source.AWSParameterStore/ # AWS Parameter Store source
Spirantis.Extensions.Configuration.Source.AWSParameterStore.Tests/
Spirantis.Extensions.Logging/ # core Serilog logging library
Spirantis.Extensions.Logging.Tests/
Spirantis.Extensions.Logging.Sink.Console/ # console sinks (text + JSON)
Spirantis.Extensions.Logging.Sink.Console.Tests/
Spirantis.Extensions.Logging.Sink.File/ # rolling-file sink
Spirantis.Extensions.Logging.Sink.AWSCloudWatch/ # AWS CloudWatch sink
Spirantis.Extensions.Logging.Sink.Syslog/ # local syslog sink (Linux)
Spirantis.Extensions.DependencyInjection.Autofac/ # Autofac named DI helpers
Spirantis.Extensions.DependencyInjection.Autofac.Tests/
Spirantis.Extensions.Hosting/ # priority-ordered hosted services
Spirantis.Extensions.Hosting.Tests/
Spirantis.Extensions.Hosting.Autofac/ # Autofac registration glue
Spirantis.Extensions.Hosting.Autofac.Tests/
Extension methods for common System types. All extensions live in the System
namespace, so they're available without an extra using once the package is
referenced.
dotnet add package Spirantis.Extensions.SystemDateTime now = DateTime.UtcNow;
// Milliseconds since the Unix epoch (floored)
double ms = now.ToMillisecondTimestamp();
// Minutes elapsed since midnight (0–1439)
int minutes = now.ToMinutesSinceMidnight();
// Seconds elapsed since midnight (0–86399)
int seconds = now.ToSecondsSinceMidnight();Trim a whole substring (not just individual characters) from either end, with a
configurable StringComparison:
"file.txt.txt".TrimEnd(".txt", StringComparison.Ordinal);
// => "file"
" prefix-prefix-value".AsSpan()
.TrimStart("prefix-", StringComparison.Ordinal);
// => "value" (span overload, allocation-free)Overloads are provided for both string (returns string) and
ReadOnlySpan<char> (returns ReadOnlySpan<char>, no allocation).
Find every type that derives from a given base type or open generic, at any depth:
Type[] allTypes = typeof(MyClass).Assembly.GetTypes();
// Non-generic base type (transitive — all descendants)
IEnumerable<Type> shapes = allTypes.Derives(typeof(Shape));
// Open generic base type (e.g. all types deriving from Repository<T>)
IEnumerable<Type> repos = allTypes.Derives(typeof(Repository<>));Asynchronous coordination primitives that fill gaps in the built-in BCL types.
dotnet add package Spirantis.Extensions.ThreadingFifoSemaphore— an async semaphore that grants entry in strict first-in, first-out order (SemaphoreSlimdoes not guarantee ordering).FunctionExecutionQueue— runs async actions one at a time, in enqueue order.KeyedFifoSemaphore— per-key FIFO mutual exclusion; locks on the same key serialize, different keys run concurrently.KeyedFunctionExecutionQueue<TKey>— aFunctionExecutionQueueper key.
See the package README for full usage examples.
Composable application configuration. AddConfiguration layers environment variables
and command-line arguments, runs a set of pluggable IConfigurationSourceAgent
instances, then re-applies command-line arguments so they take final precedence.
dotnet add package Spirantis.Extensions.Configurationusing Microsoft.Extensions.Configuration;
using Spirantis.Extensions.Configuration;
var configuration = new ConfigurationBuilder()
.AddConfiguration(
switchMappings: new Dictionary<string, string>(),
commandLineArgs: args,
options =>
{
options.ConfigurationSourceAgents.Add(new ServiceJsonFileSourceAgent());
options.ConfigurationSourceAgents.Add(new AWSParameterStoreSourceAgent());
})
.Build();Two source agent packages are provided:
Spirantis.Extensions.Configuration.Source.Json—ServiceJsonFileSourceAgent(service-localconfig.json) andGlobalJsonFileSourceAgent(machine-wideconfig.jsondiscovered across configurable, origin-neutral search paths).Spirantis.Extensions.Configuration.Source.AWSParameterStore—AWSParameterStoreSourceAgent, loading parameters recursively from AWS Systems Manager Parameter Store and flattening JSON values into configuration keys.
See the package READMEs (core, JSON, AWS) for full usage details.
Serilog-based application logging. UseLogging wires Serilog into the host (classic
IHostBuilder or modern IHostApplicationBuilder), drives minimum levels from the
Logging configuration section, and runs a set of pluggable ILoggingSink outputs —
the same composition pattern as the configuration package.
dotnet add package Spirantis.Extensions.Loggingusing Spirantis.Extensions.Logging;
var builder = Host.CreateApplicationBuilder(args);
builder.UseLogging(options =>
{
options.LoggingSinks.Add(new ConsoleSink());
options.LoggingSinks.Add(new FileSink());
});Each sink is its own package and activates only when its Logging:<Name>:Enabled flag is
set: Console (themed text + structured JSON), File (async rolling), AWSCloudWatch,
and Syslog (Linux). The core also provides structured event logging
(LogEntryEvent<TKey> + logger.LogInformation(event)) and structured REST helpers
(logger.LogIncomingRequest(...)), both capturing named properties rather than flattening
them into the message text.
See the package README for full usage details.
Spirantis.Extensions.DependencyInjection.Autofac provides Autofac helpers for named
IOptions<T> registration and for wiring a specific named dependency into an individual
constructor parameter at registration time:
builder.RegisterType<EventPublisher>()
.WithParameters(ParameterResolving.CreateResolvedParameter<IMessageProducer>("producer"));Spirantis.Extensions.Hosting adds priority-ordered hosted services: declare a tier and
the services start in order (Superior → Normal → Inferior) and stop in reverse.
public sealed class CacheWarmer() : ArrangeableBackgroundService(HostingArrangement.Superior)
{
protected override Task ExecuteAsync(CancellationToken stoppingToken) => /* ... */;
}
services.AddArrangeableHostedService<CacheWarmer>();The core is container-agnostic; Spirantis.Extensions.Hosting.Autofac adds
ContainerBuilder.RegisterArrangeableHostedService<T>() for Autofac-based composition.
Build and test the whole solution:
dotnet build Spirantis.Extensions.slnx
dotnet test Spirantis.Extensions.slnxCode is formatted with CSharpier:
csharpier format src/Each library is packed and published to nuget.org as a
separate package. Shared metadata (version, authors, license, symbol packages)
lives in src/Directory.Build.props; per-package metadata (id, description, tags)
lives in each project file.
dotnet pack src/Spirantis.Extensions.System/Spirantis.Extensions.System.csproj -c Release
dotnet pack src/Spirantis.Extensions.Threading/Spirantis.Extensions.Threading.csproj -c Release
dotnet pack src/Spirantis.Extensions.Configuration/Spirantis.Extensions.Configuration.csproj -c Release
dotnet pack src/Spirantis.Extensions.Configuration.Source.Json/Spirantis.Extensions.Configuration.Source.Json.csproj -c Release
dotnet pack src/Spirantis.Extensions.Configuration.Source.AWSParameterStore/Spirantis.Extensions.Configuration.Source.AWSParameterStore.csproj -c Release
dotnet pack src/Spirantis.Extensions.Logging/Spirantis.Extensions.Logging.csproj -c Release
dotnet pack src/Spirantis.Extensions.Logging.Sink.Console/Spirantis.Extensions.Logging.Sink.Console.csproj -c Release
dotnet pack src/Spirantis.Extensions.Logging.Sink.File/Spirantis.Extensions.Logging.Sink.File.csproj -c Release
dotnet pack src/Spirantis.Extensions.Logging.Sink.AWSCloudWatch/Spirantis.Extensions.Logging.Sink.AWSCloudWatch.csproj -c Release
dotnet pack src/Spirantis.Extensions.Logging.Sink.Syslog/Spirantis.Extensions.Logging.Sink.Syslog.csproj -c Release
dotnet pack src/Spirantis.Extensions.DependencyInjection.Autofac/Spirantis.Extensions.DependencyInjection.Autofac.csproj -c Release
dotnet pack src/Spirantis.Extensions.Hosting/Spirantis.Extensions.Hosting.csproj -c Release
dotnet pack src/Spirantis.Extensions.Hosting.Autofac/Spirantis.Extensions.Hosting.Autofac.csproj -c Release