DRN.Framework.Utils
0.7.0
Prefix Reserved
dotnet add package DRN.Framework.Utils --version 0.7.0
NuGet\Install-Package DRN.Framework.Utils -Version 0.7.0
<PackageReference Include="DRN.Framework.Utils" Version="0.7.0" />
<PackageVersion Include="DRN.Framework.Utils" Version="0.7.0" />
<PackageReference Include="DRN.Framework.Utils" />
paket add DRN.Framework.Utils --version 0.7.0
#r "nuget: DRN.Framework.Utils, 0.7.0"
#:package DRN.Framework.Utils@0.7.0
#addin nuget:?package=DRN.Framework.Utils&version=0.7.0
#tool nuget:?package=DRN.Framework.Utils&version=0.7.0
DRN.Framework.Utils
Core utilities package providing attribute-based dependency injection, configuration management, scoped logging, ambient context, and essential extensions.
TL;DR
- Attribute DI —
[Scoped<T>],[Singleton<T>],[Transient<T>]for zero-config service registration - Configuration —
IAppSettingswith typed access,[Config("Section")]bindings - Scoped Logging —
IScopedLogaggregates structured logs per request - Scoped Cancellation — Scoped
ICancellationUtilsfor request lifecycle control - Monotonic Pagination — Cursor-based pagination leveraging entity ID temporal ordering
- Bit Packing — High-performance
NumberBuilderfor custom data structures - Ambient Context —
ScopeContext.UserId,ScopeContext.Settingsanywhere - Auto-Registration —
AddServicesWithAttributes()scans and registers all attributed services - Secure Entity IDs — AES-256-ECB single-block encrypted, post-quantum secure SourceKnownEntityIds with auto-detecting
Parse
Table of Contents
- QuickStart: Beginner
- QuickStart: Advanced
- Setup
- Dependency Injection
- Configuration
- Logging (IScopedLog)
- HTTP Client Factories (IExternalRequest, IInternalRequest)
- Scope & Ambient Context (ScopeContext)
- Data Utilities
- Pagination
- Bit Packing
- Diagnostics
- Time & Async
- Concurrency
- Extensions
- Global Usings
- Related Packages
QuickStart: Beginner
Register and use a service with attribute-based DI:
// 1. Define your service with DI attribute
public interface IGreetingService { string Greet(string name); }
[Scoped<IGreetingService>]
public class GreetingService : IGreetingService
{
public string Greet(string name) => $"Hello, {name}!";
}
// 2. Register all attributed services in Startup
services.AddServicesWithAttributes();
// 3. Inject and use
public class HomeController(IGreetingService greetingService) : Controller
{
public IActionResult Index() => Ok(greetingService.Greet("World"));
}
QuickStart: Advanced
Complete example with configuration binding, scoped logging, and ambient context:
// Bind configuration section to strongly-typed class
[Config]
public class PaymentSettings
{
public string ApiKey { get; set; } = "";
public int TimeoutSeconds { get; set; } = 30;
}
// Service using scoped logging and settings
[Scoped<IPaymentService>]
public class PaymentService(IAppSettings settings, IScopedLog log, PaymentSettings config) : IPaymentService
{
public async Task<PaymentResult> ProcessAsync(decimal amount)
{
// Track execution time
using var duration = log.Measure("PaymentProcessing");
// Add structured context
log.Add("Amount", amount);
log.AddToActions("Processing payment");
// Access ambient data anywhere
var userId = ScopeContext.UserId;
// Use typed configuration
if (config.TimeoutSeconds < 10)
throw ExceptionFor.Configuration("Timeout too short");
return new PaymentResult(Success: true);
}
}
Setup
If you are using DRN.Framework.Hosting (inheriting from DrnProgramBase), this package is automatically registered and validated.
For manual installation (e.g. Console Apps, Workers):
// Registers attributes, HybridCache, and TimeProvider
builder.Services.AddDrnUtils();
HybridCache Registration
AddDrnUtils() registers Microsoft's HybridCache with default in-memory caching. To configure distributed caching (e.g., Redis), add your IDistributedCache registration before calling AddDrnUtils():
// Optional: Add distributed cache backend
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
});
// HybridCache will use the distributed cache if available
builder.Services.AddDrnUtils();
Dependency Injection
Attribute-Based Registration
Reduce configuration boilerplate by using attributes directly on services. The AddServicesWithAttributes method scans the calling assembly for these attributes and registers all services in the target assembly.
| Attribute | Lifetime | Usage |
|---|---|---|
[Singleton<T>] |
Singleton | [Singleton<IMyService>] public class MyService : IMyService |
[Scoped<T>] |
Scoped | [Scoped<IMyService>] public class MyService : IMyService |
[Transient<T>] |
Transient | [Transient<IMyService>] public class MyService : IMyService |
[SingletonWithKey<T>] |
Singleton (Keyed) | [SingletonWithKey<IMyService>("key")] |
[ScopedWithKey<T>] |
Scoped (Keyed) | [ScopedWithKey<IMyService>("key")] |
[TransientWithKey<T>] |
Transient (Keyed) | [TransientWithKey<IMyService>("key")] |
[HostedService] |
Singleton | [HostedService] public class MyWorker : BackgroundService |
[Config] |
Singleton | [Config("Section")] public class MySettings |
[ConfigRoot] |
Singleton | [ConfigRoot] public class RootSettings |
All lifetime attributes accept an optional tryAdd parameter (default: true). When true, TryAdd is used so existing registrations are not overwritten. Set to false to allow multiple implementations of the same service type.
Hosted Services
Use [HostedService] to register IHostedService/BackgroundService implementations without manual AddHostedService<T>() calls. The class must implement IHostedService; otherwise the attribute is silently ignored.
[HostedService]
public class MyBackgroundWorker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
// Do periodic work
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
}
Validation & Testing
DrnProgramBase automatically runs this validation at startup.
- Validation: Ensure all registrations are resolvable via
ValidateServicesAddedByAttributesAsync().
// In Program.cs
await app.Services.ValidateServicesAddedByAttributesAsync();
In integration tests with DRN.Framework.Testing:
[Theory, DataInlineContext]
public void Validate_Dependencies(DrnTestContext context)
{
context.ServiceCollection.AddServicesWithAttributes(); // Register local assembly
context.ValidateServices(); // Verifies resolution of all registered descriptors
}
Scoped Cancellation
Manage request-scoped cancellation tokens using ICancellationUtils. It supports merging tokens from multiple sources, such as HttpContext.RequestAborted and application-level timeouts.
public class MyScopedService(ICancellationUtils cancellation)
{
public async Task DoWorkAsync(CancellationToken externalToken)
{
// Automatically merges with the scoped token
cancellation.Merge(externalToken);
// Use the unified token
await SomeAsyncOp(cancellation.Token);
if (cancellation.IsCancellationRequested)
return;
}
}
Module Registration & Startup Actions
Services can require complex registration logic or post-startup actions. Attributes inheriting from ServiceRegistrationAttribute handle this.
Example: DrnContext<T> (in DRN.Framework.EntityFramework) is decorated with [DrnContextServiceRegistration], which:
- Registers the DbContext.
- Automatically triggers EF Core Migrations when the application starts in Development environments (via
PostStartupValidationAsync).
// The base class DrnContext handles the registration attributes.
// You just inherit from it, and your context is auto-registered with migration support.
public class MyDbContext : DrnContext<MyDbContext> { }
Configuration
IAppSettings
Access configuration using strongly-typed environment checks and utility methods.
public class MyService(IAppSettings settings)
{
public void DoWork()
{
if (settings.IsDevelopmentEnvironment) { /* dev-only logic */ }
if (settings.IsStagingEnvironment) { /* staging-only logic */ }
var conn = settings.GetRequiredConnectionString("Default");
var value = settings.GetValue<int>("MySettings:Timeout", 30);
}
}
Configuration Attributes ([Config])
Bind classes directly to configuration sections. These are registered as Singletons.
[Config("PaymentSettings")] // Binds to "PaymentSettings" section
public class PaymentOptions
{
public string ApiKey { get; set; }
}
[Config] // Binds to "FeatureFlags" section (class name)
public class FeatureFlags { ... }
[ConfigRoot] // Binds to root configuration
public class RootSettings { ... }
Configuration Sources
The framework automatically loads configuration in this order:
appsettings.json/appsettings.{Environment}.json- Environment Variables
- Mounted Settings:
/appconfig/json-settings/*.json/appconfig/key-per-file-settings/*
Override the mount directory by registering IMountedSettingsConventionsOverride.
IAppSettings Troubleshooting
| Symptom | Cause | Solution |
|---|---|---|
ConfigurationException on startup |
Missing required configuration key | Add the key to appsettings.json or environment variables |
GetRequiredConnectionString throws |
Connection string not found | Verify key exists under ConnectionStrings section |
IsDevelopmentEnvironment always false |
ASPNETCORE_ENVIRONMENT not set |
Set environment variable or use launchSettings.json |
| Mounted settings not loading | Wrong mount path | Verify files exist at /appconfig/json-settings/ or override via IMountedSettingsConventionsOverride |
| Environment variables not binding | Wrong naming format | Use __ (double underscore) for nested keys: MySection__MyKey |
DrnAppFeatures
Feature flags and runtime knobs bound from the DrnAppFeatures configuration section via [Config].
{
"DrnAppFeatures": {
"SeedData": false,
"SeedKey": "Peace at home! Peace in the world! - Mustafa Kemal Atatürk (1931)",
"DisableRequestBuffering": false,
"MaxRequestBufferingSize": 0
}
}
| Property | Type | Default | Description |
|---|---|---|---|
ApplicationStartedBy |
string? |
null |
Identifies which test started the application (set automatically by DrnTestContext). |
SeedData |
bool |
false |
Enables data seeding on startup. |
SeedKey |
string |
"Peace at home!…" |
Secret key for seed operations. Enforced [SecureKey(MinLength = 58)]. |
InternalRequestHttpVersion |
string |
"1.1" |
HTTP version used by IInternalRequest. |
InternalRequestProtocol |
string |
"http" |
Protocol scheme used by IInternalRequest (e.g., http, https). |
UseMonotonicDateTimeProvider |
bool |
false |
Experimental — switches to monotonic time provider for behavioral data collection. |
DisableRequestBuffering |
bool |
false |
Disables request body buffering entirely. Use for high-throughput services (e.g., file upload endpoints). |
MaxRequestBufferingSize |
int |
0 (→ 30,000) |
Maximum request body size to buffer in bytes. Values below 10,000 are ignored; 0 uses the 30,000-byte default. |
DisableRequestBuffering and MaxRequestBufferingSize are consumed by RequestBufferingState in DRN.Framework.Hosting. See the Hosting README for middleware details.
Logging (IScopedLog)
IScopedLog provides request-scoped structured logging. It aggregates operational data, metrics, and checkpoints during the request lifecycle, flushing them as a single entry for efficient monitoring.
Core Features
- Contextual: Automatically captures
TraceId,UserId,RequestPath, and custom scope data. - Aggregation: Groups all actions, metrics, and exceptions into a single structured log entry.
- Performance Tracking: Built-in measurement for code block durations and execution counts.
- Resilience: Captures exceptions without interrupting the business flow unless explicitly thrown.
API Usage
public class OrderService(IScopedLog logger)
{
public void ProcessOrder(int orderId)
{
// 1. Measure execution time and count
// Automatically tracks duration and increments "Stats_ProcessOrder_Count"
using var _ = logger.Measure("ProcessOrder");
// 2. Add structured data (Key-Value)
logger.Add("OrderId", orderId);
logger.AddIfNotNullOrEmpty("Referrer", "PartnerA");
// 3. Track execution checkpoints
logger.AddToActions("Validating order");
try
{
// ... logic ...
// 4. Flatten and add complex objects
logger.AddProperties("User", new { Name = "John", Role = "Admin" });
}
catch(Exception ex)
{
// 5. Log exception but keep the request contextual log intact
logger.AddException(ex, "Failed to process order");
}
}
}
HTTP Client Factories (IExternalRequest, IInternalRequest)
Wrappers around Flurl for resilient HTTP clients with standardized JSON conventions.
External Requests
Use IExternalRequest for standard external API calls. It pre-configures DefaultJsonSerializer and enforces HTTP version policies.
public class PaymentService(IExternalRequest request)
{
public async Task Process()
{
// Enforces exact HTTP version for better compatibility with modern APIs
var response = await request.For("https://api.example.com", HttpVersion.Version11)
.AppendPathSegment("v1/charges")
.PostJsonAsync(new { Amount = 1000 })
.ToJsonAsync<ExternalApiResponse>();
}
}
Internal Requests (Service Mesh)
Use IInternalRequest for Service-to-Service communication in Kubernetes. It's designed to work with Linkerd, supporting automatic protocol switching (HTTP/HTTPS) based on infrastructure settings.
Recommended Pattern: Request Wrappers
Instead of using IInternalRequest directly in business logic, wrap it in a typed request factory for better maintainability and configuration encapsulation.
// 1. Definition (External Factory Wrapper)
public interface INexusRequest { IFlurlRequest For(string path); }
[Singleton<INexusRequest>]
public class NexusRequest(IInternalRequest request, IAppSettings settings) : INexusRequest
{
private readonly string _nexusAddress = settings.NexusAppSettings.NexusAddress;
public IFlurlRequest For(string path) => request.For(_nexusAddress).AppendPathSegment(path);
}
// 2. Client Usage
public class NexusClient(INexusRequest request) : INexusClient
{
public async Task<HttpResponse<string>> GetStatusAsync() =>
await request.For("status").GetAsync().ToStringAsync();
}
Scope & Ambient Context (ScopeContext)
ScopeContext provides ambient access to request-scoped data. This simplifies cross-cutting concerns like auditing, multi-tenancy, and security by avoiding deep parameter passing especially in Razor Pages(.cshtml) files.
- Contextual Identity: Access
UserId,TraceId, andAuthenticatedstatus anywhere. - Static Accessors: Provides direct access to
IAppSettings,IScopedLog, andIServiceProvider. - RBAC Helpers: Built-in support for role and claim checks.
var currentUserId = ScopeContext.UserId;
var traceId = ScopeContext.TraceId;
var settings = ScopeContext.Settings; // Static IAppSettings access
var logger = ScopeContext.Log; // Static IScopedLog access
if (ScopeContext.IsUserInRole("Admin")) { ... }
Data Utilities
Encodings (EncodingExtensions)
Unified API for binary-to-text encodings and model serialization-encoding.
- Encodings: Base64, Base64Url (Safe for URLs), Hex, and Utf8.
- Integrated:
model.Encode(ByteEncoding.Hex)andhexString.Decode<TModel>().
Hashing (HashExtensions)
High-performance hashing extensions supporting modern and legacy algorithms.
- Blake3: Default modern cryptographic hash (fast and secure).
- XxHash3: Non-cryptographic hashing for performance-critical scenarios (IDs, Cache keys).
- Security: Keyed hashing support (
HashWithKey) for integrity protection.
JSON & Document Utilities
- JSON Merge Patch:
JsonMergePatch.SafeApplyMergePatchfollows RFC 7386 for partial updates with built-in recursion depth protection. - Query String Serialization:
QueryParameterSerializerflattens complex nested objects/arrays into clean query strings for API clients.
Serialization & Streams
- Unified Extensions:
model.Serialize(method)supports both JSON and Query String formats. - Safe Stream Consumption:
ToBinaryDataAsyncandToArrayAsyncextensions withMaxSizeGuardto prevent memory exhaustion from untrusted streams.
Programmatic Validation
Extensions for programmatic validation using System.ComponentModel.DataAnnotations.
- Contextual: Integrates with
DRN.Framework.SharedKernel.ValidationExceptionfor standardized error reporting across layers.
Pagination
The framework provides IPaginationUtils for high-performance, monotonic cursor-based pagination. It leverages the temporal sequence of SourceKnownEntityId to ensure stable results even as data is being added.
public class OrderService(IPaginationUtils pagination)
{
public async Task<PaginationResult<Order>> GetRecentOrdersAsync(PaginationRequest request)
{
var query = dbContext.Orders.Where(x => x.Active);
return await pagination.GetResultAsync(query, request);
}
}
Bit Packing
For scenarios requiring custom ID generation or compact binary data structures, use NumberBuilder and NumberParser. These ref-structs provide zero-allocation bit manipulation.
// Use NumberBuilder to pack data into a long
var builder = NumberBuilder.GetLong();
builder.TryAddNibble(0x05); // Add 4 bits
builder.TryAddUShort(65535); // Add 16 bits
long packedValue = builder.GetValue();
// Use NumberParser to unpack
var parser = NumberParser.Get(packedValue);
byte nibble = parser.ReadNibble();
ushort value = parser.ReadUShort();
// Multi-format serialization
var json = model.Serialize(SerializationMethod.SystemTextJson);
var query = model.Serialize(SerializationMethod.QueryString);
// Data Integrity
var hash = data.Hash(HashAlgorithm.Blake3);
// Secure stream conversion
var bytes = await requestStream.ToBinaryDataAsync(maxSize: 1024 * 1024);
Diagnostics
Development Status
Track database migration status and pending model changes in real-time during development.
public class StartupService(DevelopmentStatus status, IScopedLog log)
{
public void CheckStatus()
{
if (status.HasPendingChanges)
{
log.AddToActions("Warning: Pending database changes detected");
foreach (var model in status.Models)
{
model.LogChanges(log, "Development");
}
}
}
}
Time & Async
High-Performance Time (TimeStampManager)
For systems requiring frequent timestamp lookups (like ID generation or rate limiting), TimeStampManager provides a cached UTC timestamp updated periodically (default 10ms) to reduce DateTimeOffset.UtcNow overhead.
long seconds = TimeStampManager.CurrentTimestamp(EpochTimeUtils.DefaultEpoch);
DateTimeOffset now = TimeStampManager.UtcNow; // Cached precision up to the second
Async-Safe Timer (RecurringAction)
A lock-free, atomic timer implementation that prevents overlapping executions if one cycle takes longer than the period.
var worker = new RecurringAction(async () => {
await DoHeavyWork();
}, period: 1000, start: true);
worker.Stop();
ID Generation & Validation
SourceKnownEntity ID's provide reversible, type-safe, and integrity-checked identifiers.
ID generation is automatically handled by DrnContext when SourceKnownEntities are saved.
Generation Modes
The Generate method dispatches to secure or unsecure generation based on the UseSecureSourceKnownIds flag in NexusAppSettings (defaults to true). Explicit GenerateSecure and GenerateUnsecure methods are also available to bypass the flag.
| Method | Behavior |
|---|---|
Generate |
Dispatches to secure or unsecure based on UseSecureSourceKnownIds |
GenerateSecure |
AES-256-ECB encrypted — full 16-byte GUID is a ciphertext block |
GenerateUnsecure |
Plaintext with visible 4D8D version/variant markers |
ToSecure |
Converts an unsecure ID to its secure form (idempotent) |
ToUnsecure |
Converts a secure ID to its unsecure form (idempotent) |
Secure variant encrypts the entire 16-byte GUID using AES-256-ECB as a pseudo-random permutation (PRP). For a single 128-bit block, ECB is mathematically identical to CBC with a zero IV — no nonce required, no nonce-reuse vulnerability. Key separation ensures BLAKE3 keyed MAC (integrity) and AES-256 (confidentiality) use cryptographically independent keys from the same keyring entry.
Post-quantum readiness: AES-256 retains 128-bit security under Grover's algorithm — NIST recommended for post-quantum symmetric encryption.
// Generate with flag-based dispatch (secure by default)
var entityId = sourceKnownEntityIdUtils.Generate<User>(id);
// Explicitly secure
var secureId = sourceKnownEntityIdUtils.GenerateSecure<User>(id);
// Explicitly unsecure (visible markers for debugging/development)
var unsecureId = sourceKnownEntityIdUtils.GenerateUnsecure<User>(id);
// Convert between secure and unsecure forms (idempotent)
var secureId = sourceKnownEntityIdUtils.ToSecure(unsecureEntityId);
var unsecureId = sourceKnownEntityIdUtils.ToUnsecure(secureEntityId);
Parse & Validation
Parse auto-detects encrypted and plaintext IDs — it first checks for plaintext markers, then attempts AES-ECB decryption if markers are absent. Both paths verify MAC integrity.
Add rate limiting to endpoints that accept SourceKnownEntityId from untrusted sources to prevent brute-force attacks.
Users can validate incoming IDs (e.g., from APIs) using multiple approaches depending on the context:
1. Injectable Utility (Recommended for Service Layer)
var sourceKnownId = sourceKnownEntityIdUtils.Validate<User>(externalGuidId);
2. SourceKnownRepository (Recommended for Data Access)
// Method on SourceKnownRepository<TEntity>
var sourceKnownId = userRepository.GetEntityId(externalGuidId);
3. SourceKnownEntity (Recommended for Domain Logic)
// Helper on SourceKnownEntity base class
var sourceKnownId = userInstance.GetEntityId<User>(externalGuidId);
GUID Byte Layout
Each SourceKnownEntityId packs identity, integrity, time-addressing, and UUID V4 compatibility into a single 128-bit GUID:
| Byte(s) | Purpose |
|---|---|
| 0–3 | Entity ID (first half, 32 bits) |
| 4 | Entity type (8 bits — up to 256 entity types) |
| 5 | Epoch index (8 bits — up to 256 epochs) |
| 6, 9–11 | BLAKE3 keyed MAC (4 bytes — integrity verification) |
| 7 | Version marker (0x4D — UUID V4 compatible) |
| 8 | Variant marker (0x8D — RFC 4122 compatible) |
| 12–15 | Entity ID (second half, 32 bits) |
Epoch & Time Addressing
SourceKnownEntityIds use epoch-based time addressing for monotonic ordering. Each epoch spans approximately 136 years (2³¹ seconds × 2 epoch halves), starting from 2025-01-01.
| Property | Value |
|---|---|
| Epoch start | 2025-01-01 |
| Single epoch duration | ~136 years |
| Maximum epochs | 256 (byte 5) |
| Total address space | ~34,842 monotonic years |
The first epoch requires no configuration and covers approximately 136 years from 2025-01-01. Epoch transitions are handled automatically.
Time
TimeProvider singleton is registered by default to TimeProvider.System for testable time entry. See Time & Async for high-performance alternatives.
Concurrency
Lock-Free Atomic Utilities (LockUtils)
LockUtils provides static helpers for lock-free atomic operations built on Interlocked. Use these primitives to coordinate concurrent access without OS-level locks.
| Method | Purpose |
|---|---|
TryClaimLock(ref int) |
Atomically claims a lock (0 → 1). Returns true if successful. |
TryClaimScope(ref int) |
Returns a disposable LockScope that auto-releases on dispose. |
ReleaseLock(ref int) |
Unconditionally releases a lock (→ 0). |
TrySetIfEqual<T>(ref T?, T, T?) |
Atomic CAS for reference types; sets value if current equals comparand. |
TrySetIfNull<T>(ref T?, T) |
Sets value only if current is null. |
TrySetIfNotEqual<T>(ref T?, T, T?) |
Sets value only if current does not equal comparand (retry loop). |
TrySetIfNotNull<T>(ref T?, T) |
Sets value only if current is not null. |
// Disposable lock scope (preferred) — auto-releases on dispose
private int _lock;
using var scope = LockUtils.TryClaimScope(ref _lock);
if (scope.Acquired) { /* critical section */ }
// One-time initialization guard
private MyService? _instance;
var service = new MyService();
LockUtils.TrySetIfNull(ref _instance, service);
Extensions
Comprehensive set of extensions for standard .NET types and reflection.
Reflection & MethodUtils
Highly optimized reflection helpers with built-in caching for generic and non-generic method invocation.
- Invoke:
instance.InvokeMethod("Name", args)andtype.InvokeStaticMethod("Name", args). - Generics:
instance.InvokeGenericMethod("Name", typeArgs, args)with static and uncached variations. - Caching: Uses internal
ConcurrentDictionaryandrecord structkeys for zero-allocation cache lookups.
Service Collection
Advanced DI container manipulation for testing and modularity.
- Querying:
sc.GetAllAssignableTo<TService>()retrieves all descriptors matching a type. - Replacement:
ReplaceScoped,ReplaceSingleton, andReplaceInstancefor mocking/overriding dependencies in integration tests.
String & Binary Extensions
- Casing:
ToSnakeCase,ToCamelCase, andToPascalCasefor clean code-to-external system mapping. - Parsing:
string.Parse<T>()andstring.TryParse<T>(out result)using the modernIParsable<T>interface. - Binary:
ToStream()andToByteArray()shortcuts with UTF8 default. - FileSystem:
GetLines()forIFileInfowith efficient physical path reading.
Type & Assembly Extensions
- Discovery:
assembly.GetSubTypes(typeof(T))andassembly.GetTypesAssignableTo(to). - Instantiation:
assembly.CreateSubTypes<T>()automatically discovers and instantiates classes with parameterless constructors. - Metadata:
type.GetAssemblyName()returns a clean assembly name.
Flurl & HTTP Diagnostics
- Logging:
PrepareScopeLogForFlurlExceptionAsync()captures exhaustive request/response metadata from Flurl exceptions intoIScopedLog. - Status Codes:
GetGatewayStatusCode()maps API errors to standard gateway codes (502, 503, 504). - Testing:
ClearFilteredSetups()utility for complex test scenarios.
Object & Dictionary Extensions
- Deep Discovery:
instance.GetGroupedPropertiesOfSubtype(type)recursively finds properties matching a base type across complex object graphs. - Dictionary Utility: Extensions for
IDictionaryto handle null-safe value retrieval and manipulation. - Bit Manipulation:
GetBitPositions()forlongvalues and bitmask generators for signed/unsigned lengths.
// Discovery and Instantiation
var implementations = typeof(IMyInterface).Assembly.CreateSubTypes<IMyInterface>();
// Modern Parsing
int value = "123".Parse<int>();
// Casing for APIs
var key = "MyPropertyName".ToSnakeCase(); // my_property_name
Global Usings
global using DRN.Framework.SharedKernel;
global using DRN.Framework.Utils.DependencyInjection;
Related Packages
- DRN.Framework.SharedKernel - Domain primitives and exceptions
- DRN.Framework.EntityFramework - EF Core integration
- DRN.Framework.Hosting - Web application hosting
- DRN.Framework.Testing - Testing utilities
For complete examples, see Sample.Hosted.
Documented with the assistance of DiSCOS
Semper Progressivus: Always Progressive
Commit Info
Author: Duran Serkan KILIÇ
Date: 2026-03-08 23:03:03 +0300
Hash: a79b5357114f874f8a2956315f27911d316b9bac
| 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
- Blake3 (>= 2.2.0)
- DRN.Framework.SharedKernel (>= 0.7.0)
- Flurl.Http (>= 4.0.2)
- Microsoft.EntityFrameworkCore (>= 10.0.3)
- Microsoft.Extensions.Caching.Hybrid (>= 10.3.0)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.3)
- Microsoft.Extensions.Configuration.Json (>= 10.0.3)
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Identity.Stores (>= 10.0.3)
- System.IO.Hashing (>= 10.0.3)
- System.Memory.Data (>= 10.0.3)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on DRN.Framework.Utils:
| Package | Downloads |
|---|---|
|
DRN.Framework.EntityFramework
DRN.Framework.EntityFramework provides DrnContext with conventions to develop rapid and effective domain models. ## Commit Info Author: Duran Serkan KILIÇ Date: 2026-03-08 23:03:03 +0300 Hash: a79b5357114f874f8a2956315f27911d316b9bac |
|
|
DRN.Framework.Hosting
DRN.Framework.Hosting ## Commit Info Author: Duran Serkan KILIÇ Date: 2026-03-08 23:03:03 +0300 Hash: a79b5357114f874f8a2956315f27911d316b9bac |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.7.0 | 69 | 3/8/2026 |
| 0.7.0-preview067 | 75 | 3/7/2026 |
| 0.7.0-preview066 | 116 | 2/28/2026 |
| 0.7.0-preview065 | 111 | 2/25/2026 |
| 0.7.0-preview064 | 103 | 2/22/2026 |
| 0.7.0-preview063 | 109 | 2/21/2026 |
| 0.7.0-preview062 | 113 | 2/11/2026 |
| 0.7.0-preview061 | 131 | 2/7/2026 |
| 0.7.0-preview060 | 113 | 1/28/2026 |
| 0.7.0-preview059 | 113 | 1/26/2026 |
| 0.7.0-preview058 | 116 | 1/25/2026 |
| 0.7.0-preview057 | 114 | 1/25/2026 |
| 0.7.0-preview056 | 118 | 1/10/2026 |
| 0.7.0-preview055 | 290 | 12/16/2025 |
| 0.7.0-preview054 | 196 | 12/13/2025 |
| 0.7.0-preview053 | 139 | 12/12/2025 |
| 0.7.0-preview052 | 449 | 12/9/2025 |
| 0.7.0-preview051 | 323 | 12/7/2025 |
| 0.7.0-preview050 | 240 | 12/7/2025 |
| 0.7.0-preview049 | 212 | 11/26/2025 |
Not every version includes changes, features or bug fixes. This project can increment version to keep consistency with other DRN.Framework projects.
## Version 0.7.0
My family celebrates the enduring legacy of Mustafa Kemal Atatürk's enlightenment ideals and honors 8 March, International Women's Day, a cause inseparable from his vision of equality. This release is dedicated to freedom of speech, democracy, women's rights, and Prof. Dr. Ümit Özdağ, a defender of Mustafa Kemal Atatürk’s enlightenment ideals.
> [!WARNING]
> Since v0.6.0 (released 10 November 2024), substantial changes have occurred. This release notes file has been reset to reflect the current state of the project as of 08 March 2026. Previous history has been archived to maintain a clean source of truth based on the current codebase.
### New Features
* **Attribute-Based Dependency Injection**
* **Comprehensive Lifetimes**: `[Singleton]`, `[Scoped]`, `[Transient]`, `[HostedService]`, `[Config]`, `[ConfigRoot]`, and Keyed variants (`[SingletonWithKey]`, `[ScopedWithKey]`, `[TransientWithKey]`).
* **Registration**: `AddServicesWithAttributes()` auto-scans assemblies. `ValidateServicesAddedByAttributesAsync()` verifies resolution at startup.
* **Module Pattern**: `HasServiceCollectionModuleAttribute` for custom registration logic.
* **Test Helpers**: `ReplaceInstance`, `ReplaceScoped`, `ReplaceTransient`, `ReplaceSingleton` overrides for integration tests.
* **Configuration System**
* **IAppSettings**: Strong-typed access to config with support for Connection Strings and Sections.
* **Environment Helpers**: `IsDevelopmentEnvironment` and `IsStagingEnvironment` properties for explicit environment checks.
* **[Config] Attribute**: Bind classes directly to config sections (e.g., `[Config("Payment")]`). Support for `[ConfigRoot]`.
* **Layered Sources**: Loads `appsettings`, `appsettings.{Env}`, User Secrets, Env Vars, and **Mounted Settings** (`/appconfig/json-settings/*.json`, `/appconfig/key-per-file-settings`).
* **Environment-Aware Auto-Migration**: `DrnDevelopmentSettings.AutoMigrateDevelopment` (default `true`) and `AutoMigrateStaging` (default `false`) replace the previous single `AutoMigrate` flag, enabling per-environment migration control.
* **Ambient Context & Scoped Cancellation**
* **ScopeContext**: Centralized access to `UserId`, `TraceId`, `Authenticated` status, and ambient `IAppSettings`/`IScopedLog`. Built-in RBAC helpers.
* **ICancellationUtils**: Scoped cancellation management supporting token merging and lifecycle control.
* **Scoped Logging & Diagnostics**
* **IScopedLog**: Request aggregation of actions, properties, and exceptions. `Measure()` for performance tracking and counting.
* **DevelopmentStatus**: Runtime tracking of DB model changes and migration status with environment-aware migration decisions (Development and Staging).
* **Advanced Data & Bit Packing**
* **Bit Packing**: `NumberBuilder` and `NumberParser` (ref structs) for high-performance custom data structures and bit manipulation.
* **Monotonic Pagination**: `IPaginationUtils` for temporal cursor-based pagination leveraging entity IDs.
* **Cryptographic Helpers**: Unified `HashExtensions` (Blake3, XxHash3), `EncodingExtensions` (Base64, Base64Url, Hex), and `SafeApplyMergePatch` (RFC 7386).
* **HTTP & Temporal IDs**
* **Resilient HTTP**: `IInternalRequest`/`IExternalRequest` with enriched `HttpResponse<T>` diagnostics and Flurl integration.
* **Temporal IDs**: `ISourceKnownIdUtils` and `ISourceKnownEntityIdUtils` providing globally sortable identifiers.
* **Secure Entity IDs**: AES-256-ECB single-block encrypted `SourceKnownEntityId` variants with flag-based dispatch via `UseSecureSourceKnownIds` (defaults to `true`).
* `GenerateSecure` / `GenerateUnsecure` explicit methods; `Parse` auto-detects encrypted and plaintext IDs.
* Post-quantum ready — AES-256 retains 128-bit security under Grover's algorithm.
* **Epoch-Based Time Addressing**: `SourceKnownEntityId` byte 5 reserved for epoch indexing, enabling ~34,842 monotonic time years starting from 2025-01-01. Each epoch spans ~136 years (2³¹ seconds × 2 epoch halves). The first epoch requires no configuration.
* **ISourceKnownEntityIdOperations Inheritance**: `ISourceKnownEntityIdUtils` now inherits `ISourceKnownEntityIdOperations` (SharedKernel), formalizing the core contract (`Generate`, `Parse`, `ToSecure`, `ToUnsecure`) for cross-layer use without Utils dependency.
* **Secure ↔ Unsecure Conversion**: `ToSecure` / `ToUnsecure` methods (with nullable overloads) on `SourceKnownEntityIdUtils` for idempotent conversion between encrypted and plaintext `SourceKnownEntityId` forms.
* **Named Constants for GUID Layout**: Replaced magic numbers in `SourceKnownEntityIdUtils` with named constants (`GuidLength`, `MacHashLength`, `MacHashFirstIndex`–`MacHashFourthIndex`) for improved readability and maintainability.
* **Concurrency**
* **Lock-Free Atomics**: `LockUtils` static helpers (`TryClaimLock`, `TryClaimScope`, `ReleaseLock`, `TrySetIfEqual`, `TrySetIfNull`, `TrySetIfNotEqual`, `TrySetIfNotNull`) for lock-free coordination using `Interlocked`. Includes disposable `LockScope` ref struct for automatic lock release via `using`.
* **Core Extensions & Time**
* **Reflection**: Optimized `MethodUtils` with caching, `CreateSubTypes`, and deep discovery (`GetGroupedPropertiesOfSubtype`).
* **Extensions**: Robust set of `string` (Casing, Parsing), `FileInfo` (Efficient line reading), `Stream` (Size guards), and `Dictionary` utilities.
* **High-Perf Time**: `TimeStampManager` (cached UTC seconds) and `RecurringAction` (async-safe timers).
---
Documented with the assistance of [DiSCOS](https://github.com/duranserkan/DRN-Project/blob/develop/DiSCOS/DiSCOS.md)
---
**Semper Progressivus: Always Progressive**
## Commit Info
Author: Duran Serkan KILIÇ
Date: 2026-03-08 23:03:03 +0300
Hash: a79b5357114f874f8a2956315f27911d316b9bac