Moller.Utilities
1.2.0
dotnet add package Moller.Utilities --version 1.2.0
NuGet\Install-Package Moller.Utilities -Version 1.2.0
<PackageReference Include="Moller.Utilities" Version="1.2.0" />
<PackageVersion Include="Moller.Utilities" Version="1.2.0" />
<PackageReference Include="Moller.Utilities" />
paket add Moller.Utilities --version 1.2.0
#r "nuget: Moller.Utilities, 1.2.0"
#:package Moller.Utilities@1.2.0
#addin nuget:?package=Moller.Utilities&version=1.2.0
#tool nuget:?package=Moller.Utilities&version=1.2.0
Moller.Utilities
Moller.Utilities is a lightweight .NET utility library for production-friendly helpers that come up often in real applications.
Current feature areas:
- Guard and validation helpers
- Result types
- Execution helpers for repeated work, retries, and timeouts
- Disposable action wrappers
- Collection helpers
- String helpers
Target Framework
This library currently targets net10.0.
Guards
Use Validation for fluent argument and state checks.
using Moller.Utilities.Guards;
string name = "Alice";
var validatedName = Validation.For(name)
.IsNotNull()
.IsNotEmpty()
.IsNotNullOrWhiteSpace()
.Ensure(x => x!.Length <= 50, "Name must be 50 characters or fewer.")
.Value();
Instance-style syntax is still available:
using Moller.Utilities.Guards;
string connectionName = "Primary";
var value = connectionName
.Validate()
.IsNotNull()
.IsNotEmpty()
.Value();
Results
Use Result and Result<T> when failure is an expected outcome and exceptions would be too heavy.
using Moller.Utilities.Results;
Result<int> ParsePort(string value)
{
return int.TryParse(value, out var port) && port > 0
? Result<int>.Success(port)
: Result<int>.Failure("The port must be a positive integer.");
}
var portResult = ParsePort("8080");
var timeoutSeconds = portResult.Map(port => port / 1000);
Execution
PeriodicActionRunner
PeriodicActionRunner runs an Action immediately, then repeats it on a fixed interval using a background task.
using Moller.Utilities.Execution;
using var runner = new PeriodicActionRunner();
runner.Start(() =>
{
Console.WriteLine($"Heartbeat: {DateTimeOffset.Now}");
}, intervalMilliseconds: 1000);
await Task.Delay(5000);
await runner.StopAsync();
RetryPolicy
Use RetryPolicyBuilder to retry transient failures. Logging is built in when you provide an ILogger.
using Microsoft.Extensions.Logging;
using Moller.Utilities.Execution;
RetryPolicy retryPolicy = new RetryPolicyBuilder()
.WithMaxAttempts(3)
.WithExponentialBackoff(TimeSpan.FromMilliseconds(100))
.WithLogger(loggerFactory.CreateLogger("RetryPolicy"))
.Build();
await retryPolicy.ExecuteAsync(async cancellationToken =>
{
await CallRemoteServiceAsync(cancellationToken);
});
TimeoutPolicy
Use TimeoutPolicyBuilder to fail fast when work takes too long.
using Microsoft.Extensions.Logging;
using Moller.Utilities.Execution;
TimeoutPolicy timeoutPolicy = new TimeoutPolicyBuilder()
.After(TimeSpan.FromSeconds(2))
.WithLogger(loggerFactory.CreateLogger("TimeoutPolicy"))
.Build();
await timeoutPolicy.ExecuteAsync(async cancellationToken =>
{
await DoWorkAsync(cancellationToken);
});
Disposables
DisposableAction and AsyncDisposableAction make cleanup scopes easy to express.
using Moller.Utilities.Disposables;
using var cleanup = new DisposableAction(() => Console.WriteLine("Cleaning up."));
await using var asyncCleanup = new AsyncDisposableAction(() => ValueTask.CompletedTask);
Collections
The collection extensions focus on high-value helpers instead of trying to replace LINQ.
using Moller.Utilities.Collections;
var batches = Enumerable.Range(1, 10).Batch(3);
var cache = new Dictionary<string, int>();
var answer = cache.GetValueOrAdd("answer", _ => 42);
await Enumerable.Range(1, 5).ForEachAsync(
async (value, cancellationToken) =>
{
await Task.Delay(10, cancellationToken);
Console.WriteLine(value);
},
maxDegreeOfParallelism: 2);
Text
The text helpers cover a small set of common string operations.
using Moller.Utilities.Text;
string? normalized = " hello ".NullIfWhiteSpace();
string preview = "This is a longer sentence".Truncate(12);
string masked = "1234567890".Mask(unmaskedPrefix: 2, unmaskedSuffix: 2);
string csv = ", ".JoinNonEmpty("alpha", null, " beta ");
string slug = "Crème brûlée".ToSlug();
Logging
Logging is intentionally built into the operational helpers only:
PeriodicActionRunnerRetryPolicyTimeoutPolicy
Pure value helpers like results, collections, text helpers, and disposable wrappers do not log internally.
Each accepts an optional ILogger (or ILogger<T>) via its constructor or builder. If no logger is provided, a NullLogger is used and no output is produced.
Serilog Example
using Moller.Utilities.Execution;
using Microsoft.Extensions.Logging;
using Serilog;
// dotnet add package Serilog
// dotnet add package Serilog.Sinks.File
// dotnet add package Serilog.Extensions.Logging
var serilogLogger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File(
path: "logs\\myapp-.log",
rollingInterval: RollingInterval.Day,
outputTemplate:
"{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}")
.CreateLogger();
using ILoggerFactory loggerFactory =
new LoggerFactory().AddSerilog(serilogLogger, dispose: true);
ILogger<PeriodicActionRunner> logger =
loggerFactory.CreateLogger<PeriodicActionRunner>();
var runner = new PeriodicActionRunner(logger);
Notes
PeriodicActionRunner.Start(...)throws if the runner is already active.StopAsync()is safe to call even if the runner was never started.RetryPolicyretries all exceptions by default unless you narrow handled exception types.TimeoutPolicythrowsTimeoutExceptionwhen the timeout window is exceeded.Validation.IsInRange(...)and the ordering helpers support comparable types broadly, including strings and common BCL types likeDateTime,DateOnly,TimeSpan, andVersion.Validation.IsPositive(),IsNegative(), andIsNotZero()remain numeric-only.- The package introduces no new external dependencies beyond
Microsoft.Extensions.Logging.
License
MIT License
| Product | Versions 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. |
-
net10.0
- Microsoft.Extensions.Logging (>= 10.0.3)
GitHub repositories
This package is not used by any popular GitHub repositories.