TwoRivers.Core
1.1.6
dotnet add package TwoRivers.Core --version 1.1.6
NuGet\Install-Package TwoRivers.Core -Version 1.1.6
<PackageReference Include="TwoRivers.Core" Version="1.1.6" />
<PackageVersion Include="TwoRivers.Core" Version="1.1.6" />
<PackageReference Include="TwoRivers.Core" />
paket add TwoRivers.Core --version 1.1.6
#r "nuget: TwoRivers.Core, 1.1.6"
#:package TwoRivers.Core@1.1.6
#addin nuget:?package=TwoRivers.Core&version=1.1.6
#tool nuget:?package=TwoRivers.Core&version=1.1.6
TwoRivers.Core
The TwoRivers.Core library provides fundamental utilities, value objects, and extensions used across the TwoRivers Application Framework. This package includes common types for email handling, string manipulation, natural sorting, IP address utilities, and base classes for common patterns.
Installation
You can install the TwoRivers.Core package via NuGet Package Manager Console:
Install-Package TwoRivers.Core
Or via .NET CLI:
dotnet add package TwoRivers.Core
Features
- DisposableBase - Safe IAsyncDisposable and IDisposable pattern
- Value Objects (Email, EmailAddress)
- NaturalComparer
- Extension Methods
- Comparers
- Reflection Utilities
DisposableBase - Safe IAsyncDisposable and IDisposable pattern
Base class for implementing the dispose pattern correctly:
public class MyTestFixture : DisposableBase
{
private HttpClient? _httpClient; // IDisposable only
private DbConnection? _dbConnection; // IAsyncDisposable
protected override void Dispose(Boolean disposing)
{
if (disposing)
{
_httpClient?.Dispose();
_httpClient = null;
}
base.Dispose(disposing);
}
protected override async ValueTask DisposeAsyncCore()
{
if (_dbConnection is not null)
{
await _dbConnection.DisposeAsync().ConfigureAwait(false);
_dbConnection = null;
}
// HttpClient also implements IAsyncDisposable in modern .NET
if (_httpClient is IAsyncDisposable asyncDisposable)
{
await asyncDisposable.DisposeAsync().ConfigureAwait(false);
}
else
{
_httpClient?.Dispose();
}
_httpClient = null;
await base.DisposeAsyncCore().ConfigureAwait(false);
}
}
How does a derived class know which dispose to override?
| Scenario | Override |
|---|---|
Async resources (e.g., IAsyncDisposable fields, async streams) |
DisposeAsyncCore() |
Sync-only resources (e.g., IDisposable fields, unmanaged handles) |
Dispose(Boolean) |
| Mixed resources | Both methods |
The key insight: when DisposeAsync() is called, it calls DisposeAsyncCore() first (cleaning
managed resources async), then Dispose(false) (cleaning only unmanaged resources). This
prevents double-disposal of managed resources.
Value Objects
Strongly-typed email address value object with validation:
using TwoRivers.Emailing;
var email = new Email("user@example.com");
Console.WriteLine(email.Domain); // "example.com"
Console.WriteLine(email.LocalPart); // "user"
EmailAddress
Combines display name and email address (compatible with System.Net.Mail.MailAddress):
using TwoRivers.Emailing;
var emailAddress = new EmailAddress("John Doe", "john@example.com");
var mailAddress = (MailAddress)emailAddress; // Implicit conversion
// Or parse from string
var parsed = new EmailAddress("John Doe <john@example.com>");
NaturalComparer
Compares strings using natural (human-friendly) ordering where numbers are compared numerically:
using TwoRivers;
var files = new[] { "file10.txt", "file2.txt", "file1.txt" };
Array.Sort(files, new NaturalComparer<String>());
// Result: ["file1.txt", "file2.txt", "file10.txt"]
Extension Methods
StringExtensions
Common string manipulation utilities:
using TwoRivers.Extensions;
// Left substring
var text = "Hello World";
var left = text.Left(5); // "Hello"
// Truncate with ellipsis
var truncated = text.Truncate(8); // "Hello ..."
// Remove whitespace
var clean = " lots of spaces ".RemoveWhitespace(); // "lotsofspaces"
IPAddressExtensions
IP address utilities:
using TwoRivers.Extensions;
using System.Net;
var ip = IPAddress.Parse("192.168.1.100");
var network = IPAddress.Parse("192.168.1.0");
if (ip.IsInSameSubnet(network, 24))
{
Console.WriteLine("Same subnet");
}
MiscExtensions
Miscellaneous extension methods:
using TwoRivers.Extensions;
// Clamp values
var value = 150;
var clamped = value.Clamp(0, 100); // 100
// Visit exception hierarchy
try
{
// code
}
catch (Exception ex)
{
ex.Visit(e => Console.WriteLine($"Exception: {e.Message}"));
}
Comparers
IPAddressComparer
Compares IP addresses for sorting:
using TwoRivers.Net;
var addresses = new[]
{
IPAddress.Parse("192.168.1.100"),
IPAddress.Parse("10.0.0.1"),
IPAddress.Parse("192.168.1.10")
};
Array.Sort(addresses, new IPAddressComparer());
EnumerableComparer
Compares sequences element-by-element:
using TwoRivers;
var comparer = new EnumerableComparer<Int32>();
var list1 = new[] { 1, 2, 3 };
var list2 = new[] { 1, 2, 4 };
var result = comparer.Compare(list1, list2); // < 0
Reflection Utilities
ReflectionUtils
Extract constants and metadata using reflection:
using TwoRivers.Reflection;
public static class ErrorCodes
{
public const String NotFound = "NOT_FOUND";
public const String Unauthorized = "UNAUTHORIZED";
}
// Get all constant values
var codes = ReflectionUtils.GetConstants<String>(typeof(ErrorCodes));
// Returns: ["NOT_FOUND", "UNAUTHORIZED"]
License
This project is licensed under the MIT License. See the LICENSE file for details.
This project is licensed under the MIT License. See the 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. |
-
net10.0
-
net8.0
-
net9.0
NuGet packages (7)
Showing the top 5 NuGet packages that depend on TwoRivers.Core:
| Package | Downloads |
|---|---|
|
ProvisionData.HaloPSA.ApiClient
HaloPSA API Client for .NET providing typed models and client helpers. |
|
|
TwoRivers.Results
Framework and tools for implementing applications by following best practices in a developer friendly way. Built from commit 4a4908d297d9eb550c65eed6a73acd33dc9c9acc https://github.com/TwoRiversIT/AppFramework/commit/4a4908d297d9eb550c65eed6a73acd33dc9c9acc |
|
|
TwoRivers.Testing
Framework and tools for implementing applications by following best practices in a developer friendly way. Built from commit 4a4908d297d9eb550c65eed6a73acd33dc9c9acc https://github.com/TwoRiversIT/AppFramework/commit/4a4908d297d9eb550c65eed6a73acd33dc9c9acc |
|
|
TwoRivers.IdGeneratrion
Framework and tools for implementing applications by following best practices in a developer friendly way. Built from commit 4a4908d297d9eb550c65eed6a73acd33dc9c9acc https://github.com/TwoRiversIT/AppFramework/commit/4a4908d297d9eb550c65eed6a73acd33dc9c9acc |
|
|
TwoRivers.Security
Framework and tools for implementing applications by following best practices in a developer friendly way. Built from commit 4a4908d297d9eb550c65eed6a73acd33dc9c9acc https://github.com/TwoRiversIT/AppFramework/commit/4a4908d297d9eb550c65eed6a73acd33dc9c9acc |
GitHub repositories
This package is not used by any popular GitHub repositories.