Linger.Utils
1.0.0
dotnet add package Linger.Utils --version 1.0.0
NuGet\Install-Package Linger.Utils -Version 1.0.0
<PackageReference Include="Linger.Utils" Version="1.0.0" />
<PackageVersion Include="Linger.Utils" Version="1.0.0" />
<PackageReference Include="Linger.Utils" />
paket add Linger.Utils --version 1.0.0
#r "nuget: Linger.Utils, 1.0.0"
#:package Linger.Utils@1.0.0
#addin nuget:?package=Linger.Utils&version=1.0.0
#tool nuget:?package=Linger.Utils&version=1.0.0
Linger.Utils
A comprehensive .NET utility library providing extensive extension methods and helper classes for everyday development tasks.
Overview
Linger.Utils offers a rich collection of extension methods and helper classes that make common programming tasks simpler and more efficient. The library follows modern C# coding practices, emphasizes strict type safety, and supports multiple .NET framework versions.
Table of Contents
- Features
- Installation
- Target Frameworks
- Quick Start
- Advanced Features
- Best Practices
- API Standardization & Type Safety
Features
๐ Core Extensions
- String Extensions: Rich string operations, validation, conversion, and formatting utilities
- String Cryptography Extensions: Secure AES encryption/decryption functionality for data protection
- DateTime Extensions: Date and time manipulation, formatting, and calculations
- Numeric Extensions: Type-safe numeric conversions with strict type safety principles, complete support for all .NET basic numeric types
- Enum Extensions: Enhanced enum handling and conversion
- Object Extensions: General object operations and validation, enhanced with complete numeric type support
- Array Extensions: Array processing and manipulation utilities
- GUID Extensions: GUID operation and validation utilities
๐ฆ Collection Extensions
- List Extensions: Enhanced list operations and processing
- Collection Extensions: General collection utilities and transformations
๐พ Data Extensions
- DataTable Extensions: DataTable operation utilities
- Data Conversion: Safe data type conversion and transformation
๐ File System Operations
- File Helper: Comprehensive file operations (read, write, copy, move, delete)
- Path Helper: Cross-platform path operations and validation
- Directory Operations: Directory management and traversal utilities
๐ง Helper Classes
- Expression Helper: Expression tree operations and utilities
- Retry Helper: Robust retry mechanisms for operations
- Property Helper: Reflection-based property operations
- GUID Code: Enhanced GUID generation and operations
- OS Platform Helper: Cross-platform operating system detection
- Parameter Validation Extensions: Defensive programming and input validation utilities
๐ JSON Support
- JSON Extensions: Simplified JSON serialization and deserialization
- Custom Converters: Specialized JSON converters for complex types (DateTime, DataTable, JsonObject, etc.)
- JSON Defaults:
JsonDefaultsprovides unified JSON serialization configuration- Detailed documentation:
Linger/Json/JsonDefaults.README.md
- Detailed documentation:
Installation
dotnet add package Linger.Utils
Target Frameworks
- .NET 10.0
- .NET 9.0
- .NET 8.0
- .NET Standard 2.0
- .NET Framework 4.7.2
Quick Start
String Extensions
using Linger.Extensions.Core;
// String validation
string email = "user@example.com";
bool isValid = email.IsEmail();
// String conversion
string number = "123";
int result = number.ToIntOrDefault(0); // Returns 123, or 0 if conversion fails
int? nullableResult = number.ToIntOrNull(); // Returns nullable type
// String manipulation
string text = " Hello World ";
string cleaned = text.Trim(); // Removes whitespace from both ends (.NET native method)
// String extraction
string longText = "Hello World";
string leftPart = longText.Take(5); // Get left 5 characters: Hello
string rightPart = longText.TakeLast(5); // Get right 5 characters: World
string part = longText.Truncate(20); // Won't throw if length exceeds
// String checks
bool isEmpty = text.IsNullOrEmpty();
bool isNumber = number.IsNumber(); // Check if it's a number
bool isInt = number.IsInteger(); // Check if it's an integer
String Cryptography Extensions
using Linger.Extensions.Core;
string data = "Sensitive data to encrypt";
string aesKey = "mySecretKey12345"; // AES key
// AES Encryption/Decryption (Recommended - High Security)
string aesEncrypted = data.AesEncrypt(aesKey); // AES-256-CBC mode, auto-generates random IV
string aesDecrypted = aesEncrypted.AesDecrypt(aesKey); // Auto-extracts IV and decrypts
// โจ Security Features:
// - Random IV per encryption, same plaintext produces different ciphertext
// - Variable key length, internally uses SHA256 to process to 32 bytes
// - IV automatically included in ciphertext, auto-extracted during decryption
// โ ๏ธ Store keys securely, use professional key management solutions in production
DateTime Extensions
using Linger.Extensions.Core;
DateTime date = DateTime.Now;
// Age calculation
DateTime birthDate = new DateTime(1990, 5, 15);
int age = birthDate.CalculateAge();
// Date range operations
bool isInRange = date.InRange(DateTime.Today, DateTime.Today.AddDays(7));
// Date operations
DateTime startOfDay = date.StartOfDay(); // Beginning of the day
DateTime endOfDay = date.EndOfDay(); // End of the day
DateTime startOfMonth = date.StartOfMonth(); // Beginning of the month
DateTime endOfMonth = date.EndOfMonth(); // End of the month
File Operations
using Linger.Helper;
// File operations
FileHelper.WriteText("data.txt", "Hello World");
string content = FileHelper.ReadText("data.txt");
// File copy with directory creation
FileHelper.CopyFile("source.txt", "backup/dest.txt");
// Safe file deletion
FileHelper.DeleteFileIfExists("temp.txt");
// Directory operations
FileHelper.EnsureDirectoryExists("logs/2024");
Collection Extensions
using Linger.Extensions.Collection;
var list = new List<int> { 1, 2, 3, 4, 5 };
// Safe collection state checking
bool isEmpty = list.IsNullOrEmpty(); // Check if null or empty
// Pagination
var pagedResult = list.Paging(2, 2); // Page 2, 2 items per page: [3, 4]
// Convert to delimited string
string result = list.ToSeparatedString(", "); // "1, 2, 3, 4, 5"
// Execute action on each element
list.ForEach(Console.WriteLine); // Print each element
// Convert to DataTable
var dataTable = list.Select(x => new { Value = x }).ToDataTable();
// ๐ .NET 10+ Join operations โ compatibility (now supported)
// ๐ก Note: Polyfill implementations are used on older target frameworks; on .NET 10+ targets the framework native implementations will be used
// Left Join (Left Outer Join) - Keep all left-side records
var employees = new List<Employee>
{
new Employee { Id = 1, Name = "John", DeptId = 1 },
new Employee { Id = 2, Name = "Jane", DeptId = 2 },
new Employee { Id = 3, Name = "Bob", DeptId = 99 } // No matching department
};
var departments = new List<Department>
{
new Department { Id = 1, Name = "Development" },
new Department { Id = 2, Name = "Testing" }
};
var leftJoinResult = employees.LeftJoin(
departments,
emp => emp.DeptId, // Outer key selector
dept => dept.Id, // Inner key selector
(emp, dept) => new {
Employee = emp.Name,
Department = dept?.Name ?? "No Department"
}
);
// Output: John-Development, Jane-Testing, Bob-No Department
// Right Join (Right Outer Join) - Keep all right-side records
var rightJoinResult = employees.RightJoin(
departments, emp => emp.DeptId, dept => dept.Id,
(emp, dept) => new { Employee = emp?.Name ?? "No Employee", Department = dept.Name }
);
// Full Join (Full Outer Join) - Keep all records
var fullJoinResult = employees.FullJoin(
departments, emp => emp.DeptId, dept => dept.Id,
(emp, dept) => new { Employee = emp?.Name ?? "No Employee", Department = dept?.Name ?? "No Department" }
);
// ๐ก Simplified version: Returns tuples
var tupleResult = employees.LeftJoin(departments, e => e.DeptId, d => d.Id);
// Returns IEnumerable<Tuple<Employee, Department?>>
// ๐ก Support for custom equality comparers
var caseInsensitiveJoin = stringList1.LeftJoin(
stringList2, s => s, s => s,
(s1, s2) => new { Left = s1, Right = s2 },
StringComparer.OrdinalIgnoreCase
);
// โ
.NET 10+ Built-in Compatible: Method signatures match the standard, no code changes required when upgrading
Object Extensions
using Linger.Extensions.Core;
// Type-safe object conversion
object stringObj = "123";
int intValue = stringObj.ToIntOrDefault(0); // Success: 123
long longValue = stringObj.ToLongOrDefault(0L); // Success: 123
double doubleValue = stringObj.ToDoubleOrDefault(0.0); // Success: 123.0
// Strict type safety: Non-string objects return default values
object numberObj = 123.45;
int invalidInt = numberObj.ToIntOrDefault(0); // Returns 0 (default value)
// ๐ Supported numeric type conversions
| Method | Range | Method | Range |
|--------|-------|--------|-------|
| `ToSByteOrDefault` | -128 to 127 | `ToByteOrDefault` | 0 to 255 |
| `ToShortOrDefault` | -32,768 to 32,767 | `ToUShortOrDefault` | 0 to 65,535 |
| `ToIntOrDefault` | ยฑ2.1ร10โน | `ToUIntOrDefault` | 0 to 4.3ร10โน |
| `ToLongOrDefault` | ยฑ9.2ร10ยนโธ | `ToULongOrDefault` | 0 to 1.8ร10ยนโน |
| `ToFloatOrDefault` | Single precision | `ToDoubleOrDefault` | Double precision |
| `ToDecimalOrDefault` | High precision | - | - |
// Other type conversions
DateTime dateValue = stringObj.ToDateTimeOrDefault(DateTime.MinValue);
Guid guidValue = "550e8400-e29b-41d4-a716-446655440000".ToGuidOrDefault();
bool boolValue = stringObj.ToBoolOrDefault(false);
// Null-safe operations
object obj = GetSomeObject();
string result = obj.ToStringOrDefault("default"); // Returns default when null
// ๐ Type checking methods (supports all numeric types)
object testObj = (byte)255;
bool isByte = testObj.IsByte(); // Check if byte type
bool isNumeric = testObj.IsNumeric(); // Check if any numeric type
bool isUnsigned = testObj.IsAnyUnsignedInteger(); // Check if unsigned integer type
// ? Performance-optimized Try-style conversion - avoid default value masking failure
if ("123".TryToInt(out var parsedInt)) { /* parsedInt = 123 */ }
if (!"bad data".TryToDecimal(out var decVal)) { /* decVal = 0, conversion failed */ }
// Try-style numeric conversions (to avoid masking failures with defaults)
if ("123".TryToInt(out var parsedInt)) { /* parsedInt = 123 */ }
if (!"bad data".TryToDecimal(out var decVal)) { /* decVal = 0, conversion failed */ }
> Naming convention: All Try-style methods use `TryToXxx(out T)` and return `bool`. For string extensions the `out` parameter is a nullable value type (e.g., `out int?`), while for object extensions it is non-nullable (e.g., `out int`).
// Ensure prefix/suffix (idempotent, won't duplicate)
var apiUrl = "api/v1".EnsureStartsWith("/"); // => "/api/v1"
var folder = "logs".EnsureEndsWith("/"); // => "logs/"
// Range checking (for numeric values)
int value = 5;
bool inRange = value.InRange(1, 10); // Check if in range 1 to 10
JSON Extensions
using Linger.Extensions;
using Linger.Json;
// Object to JSON
var user = new { Name = "John", Age = 30 };
string json = user.ToJsonString(); // or user.SerializeJson()
// JSON to object
var userObj = json.Deserialize<User>(); // or json.DeserializeJson<User>()
// Dynamic JSON object
dynamic dynamicObj = json.DeserializeDynamicJsonObject();
string name = dynamicObj.Name; // Access properties
// JSON to DataTable (string extension)
string jsonArray = "[{\"Name\":\"John\",\"Age\":30}]";
DataTable? dataTable = jsonArray.ToDataTable();
// ๐ญ Use JsonDefaults for unified configuration
var responseOptions = JsonDefaults.CreateResponseOptions(); // HTTP responses
var requestOptions = JsonDefaults.CreateRequestOptions(); // HTTP requests
// Apply configuration in WebAPI
builder.Services.AddControllers()
.AddJsonOptions(options =>
JsonDefaults.ApplyDefaultConfiguration(options.JsonSerializerOptions));
// ๐ก For detailed configuration documentation, see: Linger/Json/JsonDefaults.README.md
GUID Extensions
using Linger.Extensions.Core;
// GUID checking
Guid guid = Guid.NewGuid();
bool isEmpty = guid.IsEmpty(); // Check if empty GUID
bool isNotEmpty = guid.IsNotEmpty(); // Check if not empty
// Nullable GUID operations
Guid? nullableGuid = null;
bool isNull = nullableGuid.IsNull(); // Check if null
bool isNotNull = nullableGuid.IsNotNull(); // Check if not null
bool isNullOrEmpty = nullableGuid.IsNullOrEmpty(); // Check if null or empty
bool isNotNullOrEmpty = nullableGuid.IsNotNullOrEmpty(); // Check if neither null nor empty
// GUID conversion
long longValue = guid.ToInt64(); // Convert to Int64
int intValue = guid.ToInt32(); // Convert to Int32
// .NET 9+ feature: V7 GUID timestamp extraction
#if NET9_0_OR_GREATER
DateTimeOffset timestamp = guid.GetTimestamp(); // Only for V7 GUIDs
#endif
Array Extensions
using Linger.Extensions.Core;
int[] numbers = { 1, 2, 3, 4, 5 };
// Execute action on each element
numbers.ForEach(n => Console.WriteLine(n)); // Output: 1 2 3 4 5
// Iterate with index
numbers.ForEach((n, index) => Console.WriteLine($"Index {index}: {n}"));
// Output: Index 0: 1, Index 1: 2, ...
Enum Extensions
using Linger.Extensions.Core;
public enum Status
{
Active = 1,
Inactive = 2,
Pending = 3
}
// String to enum
string statusName = "Active";
Status status = statusName.GetEnum<Status>(); // or statusName.ToEnum<Status>()
// Integer to enum
int statusValue = 1;
Status statusFromInt = statusValue.GetEnum<Status>();
// Get enum name
string enumName = statusValue.GetEnumName<Status>(); // Returns "Active"
// Get enum description (if Description attribute exists)
string description = status.GetDescription(); // Get description text
Parameter Validation
using Linger;
public void ProcessData(string data, IEnumerable<int> numbers)
{
// ๐ Parameter validation polyfill for pre-.NET 8 versions
ArgumentNullException.ThrowIfNull(data); // Ensure not null
ArgumentException.ThrowIfNullOrEmpty(data); // Ensure not null or empty string
ArgumentException.ThrowIfNullOrWhiteSpace(data); // Ensure not null, empty or whitespace
ArgumentNullException.ThrowIfNull(numbers); // Ensure collection is not null
// ? Framework support: .NET 6+ uses built-in implementation, .NET 5 and below uses Linger Polyfill
// When upgrading to .NET 8+, just remove "using Linger;", no other code changes required
}
Advanced Features
Retry Helper
using Linger.Helper;
// Retry operation with configurable policy
var options = new RetryOptions
{
MaxRetryAttempts = 3,
DelayMilliseconds = 1000, // 1 second
MaxDelayMilliseconds = 5000,
UseExponentialBackoff = true,
Jitter = 0.2
};
var retryHelper = new RetryHelper(options);
var result = await retryHelper.ExecuteAsync(
async () => await SomeOperationThatMightFail(),
"Operation Name"
);
// Or use default options
var defaultRetryHelper = new RetryHelper();
var result2 = await defaultRetryHelper.ExecuteAsync(
async () => await AnotherOperationThatMightFail(),
"Another Operation Name"
);
// Synchronous variant
defaultRetryHelper.Execute(() => DoSomething());
// Try-style file writing
FileHelper.TryWriteText("logs/app.log", "hello world");
FileHelper.TryAppendText("logs/app.log", "\nnext line");
Expression Helper
using Linger.Helper;
using Linger.Enums;
// Dynamic expression building
// Basic expressions
Expression<Func<User, bool>> trueExpression = ExpressionHelper.True<User>();
Expression<Func<User, bool>> falseExpression = ExpressionHelper.False<User>();
// Single condition expressions
Expression<Func<User, bool>> ageFilter = ExpressionHelper.CreateGreaterThan<User>("Age", "18");
Expression<Func<User, bool>> nameFilter = ExpressionHelper.GetContains<User>("Name", "John");
// Build complex expressions using condition collections
var conditions = new List<Condition>
{
new Condition { Field = "Age", Op = CompareOperator.GreaterThan, Value = 18 },
new Condition { Field = "Name", Op = CompareOperator.Contains, Value = "John" }
};
Expression<Func<User, bool>> complexFilter = ExpressionHelper.BuildLambda<User>(conditions);
Path Operations
using Linger.Helper.PathHelpers;
// Path normalization - handles relative paths, duplicate separators, etc.
string messyPath = @"C:\temp\..\folder\.\file.txt";
string normalized = StandardPathHelper.NormalizePath(messyPath);
// Result: "C:\folder\file.txt" (Windows) or "/folder/file.txt" (Unix)
// Path comparison - cross-platform safe path equality check
string path1 = @"C:\Users\Documents\file.txt";
string path2 = @"c:\users\documents\FILE.TXT"; // Different case
bool pathEquals = StandardPathHelper.PathEquals(path1, path2); // Windows: true, Linux: false
// Get relative path - from base path to target path
string basePath = @"C:\Projects\MyApp";
string targetPath = @"C:\Projects\MyApp\src\Components\Button.cs";
string relative = StandardPathHelper.GetRelativePath(basePath, targetPath);
// Result: "src\Components\Button.cs" (Windows) or "src/Components/Button.cs" (Unix)
// Resolve absolute path - convert relative path to absolute
string workingDir = @"C:\Projects";
string relativePath = @"MyApp\src\file.txt";
string absolutePath = StandardPathHelper.ResolveToAbsolutePath(workingDir, relativePath);
// Result: "C:\Projects\MyApp\src\file.txt"
// Check for invalid path characters
string suspiciousPath = "file<name>.txt"; // Contains invalid character '<'
bool hasInvalidChars = StandardPathHelper.ContainsInvalidPathChars(suspiciousPath); // true
// Check if file or directory exists
string filePath = @"C:\temp\data.txt";
bool fileExists = StandardPathHelper.Exists(filePath, checkAsFile: true); // Check as file
bool dirExists = StandardPathHelper.Exists(filePath, checkAsFile: false); // Check as directory
// Get parent directory path
string deepPath = @"C:\Projects\MyApp\src\Components\Button.cs";
string parentDir = StandardPathHelper.GetParentDirectory(deepPath, levels: 1);
// Result: "C:\Projects\MyApp\src\Components"
string grandParentDir = StandardPathHelper.GetParentDirectory(deepPath, levels: 2);
// Result: "C:\Projects\MyApp\src"
API Standardization & Type Safety
.NET 10 Forward-Compatible Design
Methods like LeftJoin, RightJoin, FullJoin are fully compatible with .NET 10 standard. Zero code changes required when upgrading. Automatically switches via conditional compilation #if !NET10_0_OR_GREATER.
Strict Type Safety Principles
Conversion Strategy (Performance Optimized):
- First checks direct type matching (zero overhead)
- Then attempts
ToString()to string parsing
object intObj = 123;
int result = intObj.ToIntOrDefault(0); // Direct match, zero overhead
object doubleObj = 123.45;
int failed = doubleObj.ToIntOrDefault(0); // Returns 0 (conversion fails)
Complete Numeric Type Support: byte, sbyte, short, ushort, int, uint, long, ulong, float, double, decimal
Performance Benefits
- ? Zero-overhead same-type conversion
- ? Avoids exceptions, returns default values for better performance
- ? Smart fallback strategy, string conversion only when needed
- ? Unified API naming pattern
Best Practices
- Type Conversion: Use
ToXxxOrDefault()to avoid exception overhead; useTryToXxx()methods when you need to explicitly check if conversion succeeds - Null Checking: Leverage
IsNullOrEmpty(),EnsureIsNotNull()and other extension methods - Async Operations: Use async versions for I/O-intensive tasks (file, network)
- Exception Handling: Use
RetryHelperfor unstable operations, handle exceptions properly with user feedback - Resource Management: Use
usingstatements to ensure proper resource disposal
Polyfills Summary
Provides forward-compatible Polyfills for BCL APIs & language features (for .NET Framework/Standard 2.0/legacy versions). Uses conditional compilation to automatically defer to framework built-ins when upgraded.
| Category | Content | Source Location |
|---|---|---|
| Parameter Validation | ArgumentNullException.ThrowIfNull (pre-.NET 6)<br>ArgumentException.ThrowIfNullOrEmpty/WhiteSpace (pre-.NET 8) |
Polyfills/ArgumentNullException.cs<br>Polyfills/ArgumentException.cs |
| Language Features | required keyword support (C# 11)<br>RequiredMemberAttribute, SetsRequiredMembersAttribute, CompilerFeatureRequiredAttribute |
Polyfills/RequiredMemberAttribute.cs<br>Polyfills/SetsRequiredMembersAttribute.cs<br>Polyfills/CompilerFeatureRequiredAttribute.cs |
| Nullability Attributes | 11 attributes: AllowNull, NotNull, MaybeNullWhen, NotNullIfNotNull, etc. |
Polyfills/NullableAttributes.cs |
| Collection Extensions | LeftJoin, RightJoin, FullJoin ( .NET 10 compatible โ Polyfills retained for older targets ) |
Extensions/Collection/IEnumerableExtensions.Polyfills.cs |
| Caller Capture | CallerArgumentExpressionAttribute (improves Guard experience) |
Polyfills/CallerArgumentExpressionAttribute.cs |
Dependencies
The library has minimal external dependencies:
- System.Text.Json (for JSON operations)
- System.Data.DataSetExtensions (for .NET Framework and .NET Standard 2.0)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. Please ensure:
- Follow existing code style
- Add unit tests for new features
- Update documentation as needed
License
This project is licensed under the terms of the license provided with the Linger project.
For more information about the Linger framework and other related packages, visit the Linger Project Repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- System.Text.Json (>= 10.0.0)
-
.NETStandard 2.0
- System.Data.DataSetExtensions (>= 4.5.0)
- System.Text.Json (>= 10.0.0)
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (13)
Showing the top 5 NuGet packages that depend on Linger.Utils:
| Package | Downloads |
|---|---|
|
Linger.FileSystem
Unified file system abstraction library that provides a consistent interface for accessing different file systems (local, FTP, SFTP). Core library containing the base interfaces, models, and local file system implementation. |
|
|
Linger.Excel.Contracts
Core abstractions and interfaces for Excel manipulation in .NET applications. Provides a common API for Excel operations that can be implemented by various providers (ClosedXML, NPOI, etc.), with support for data conversion, styling, and template-based generation. |
|
|
Linger.Email
A C# email helper library that provides simplified email operations, SMTP support, HTML and plain text emails, attachment handling, and asynchronous sending capabilities. Built on top of MailKit for robust and secure email communication across multiple .NET frameworks. |
|
|
Linger.Configuration
A lightweight configuration helper library for .NET applications. Simplifies access to application settings with strongly-typed configuration binding. Provides utilities for working with appsettings.json and other configuration sources. |
|
|
Linger.EFCore
An Entity Framework Core extension library providing enhanced capabilities. Includes global query filters, property conversions for complex types, and pagination utilities. Simplifies working with JSON data, collections, and complex filtering scenarios. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 107 | 11/12/2025 |
| 1.0.0-preview2 | 520 | 11/6/2025 |
| 1.0.0-preview1 | 579 | 11/5/2025 |
| 0.9.9 | 583 | 10/16/2025 |
| 0.9.8 | 547 | 10/14/2025 |
| 0.9.7-preview | 528 | 10/13/2025 |
| 0.9.6-preview | 510 | 10/12/2025 |
| 0.9.5 | 529 | 9/28/2025 |
| 0.9.4-preview | 545 | 9/25/2025 |
| 0.9.3-preview | 546 | 9/22/2025 |
| 0.9.2-preview | 254 | 9/21/2025 |
| 0.9.1-preview | 615 | 9/16/2025 |
| 0.9.0-preview | 452 | 9/12/2025 |
| 0.8.5-preview | 711 | 8/31/2025 |
| 0.8.4-preview | 846 | 8/25/2025 |
| 0.8.3-preview | 714 | 8/20/2025 |
| 0.8.2-preview | 609 | 8/4/2025 |
| 0.8.1-preview | 502 | 7/30/2025 |
| 0.8.0-preview | 1,003 | 7/22/2025 |
| 0.7.2 | 706 | 6/3/2025 |
| 0.7.1 | 690 | 5/21/2025 |
| 0.7.0 | 688 | 5/19/2025 |
| 0.6.0-alpha | 678 | 4/28/2025 |
| 0.5.0-alpha | 690 | 4/10/2025 |
| 0.4.0-alpha | 678 | 4/1/2025 |
| 0.3.3-alpha | 637 | 3/19/2025 |
| 0.3.2-alpha | 616 | 3/17/2025 |
| 0.3.1-alpha | 634 | 3/16/2025 |
| 0.3.0-alpha | 716 | 3/6/2025 |
| 0.2.0-alpha | 418 | 2/9/2025 |
| 0.1.2-alpha | 338 | 12/17/2024 |
| 0.1.1-alpha | 323 | 12/17/2024 |
| 0.1.0-alpha | 510 | 12/6/2024 |
| 0.0.9-alpha | 208 | 11/27/2024 |
| 0.0.8-alpha | 138 | 10/21/2024 |
| 0.0.7-alpha | 117 | 10/12/2024 |
| 0.0.6-alpha | 122 | 10/12/2024 |
| 0.0.5-alpha | 118 | 10/7/2024 |
| 0.0.4-alpha | 284 | 10/3/2024 |
| 0.0.3-alpha | 302 | 8/9/2024 |
| 0.0.2-alpha | 180 | 8/9/2024 |
| 0.0.1-alpha | 179 | 7/22/2024 |