CodeMe.Basics
0.0.3
dotnet add package CodeMe.Basics --version 0.0.3
NuGet\Install-Package CodeMe.Basics -Version 0.0.3
<PackageReference Include="CodeMe.Basics" Version="0.0.3" />
<PackageVersion Include="CodeMe.Basics" Version="0.0.3" />
<PackageReference Include="CodeMe.Basics" />
paket add CodeMe.Basics --version 0.0.3
#r "nuget: CodeMe.Basics, 0.0.3"
#:package CodeMe.Basics@0.0.3
#addin nuget:?package=CodeMe.Basics&version=0.0.3
#tool nuget:?package=CodeMe.Basics&version=0.0.3
CodeMe.Basics
CodeMe.Basics is a library for simple reusable infrastructure types that are missing in BCL.
ScopedAsyncLocal<T>
ScopedAsyncLocal<T> provides ambient context for a logical execution flow. It is useful when a value should be available to all code in the current flow without explicitly passing it through every method call. Typical scenarios include unit of work scopes, request correlation identifiers, tenant information, etc.
Scenarios and example of usage
Use ScopedAsyncLocal<T> when a value should be available to the current logical execution path and reverted automatically when the scope ends. The value is visible to nested scopes and is restored to the previous ambient value when the scope is disposed.
using CodeMe.Basics.Threading;
var context = new ScopedAsyncLocal<string>();
using (context.BeginScope("request-1"))
{
Console.WriteLine(context.Current); // request-1
using (context.BeginScope("nested"))
{
Console.WriteLine(context.Current); // nested
}
Console.WriteLine(context.Current); // request-1
}
Console.WriteLine(context.Current); // null
n t
ScopedAsyncLocal<T> also works with asynchronous flows. The value from the current scope is available after await; the scope must be disposed to restore the previous value.
var local = new ScopedAsyncLocal<string>();
using (await local.BeginScopeAsync(() => new ValueTask<string>("request-2")))
{
Console.WriteLine(local.Current); // request-2
}
The constructor can be used with validateDisposeOrder: true to detect out-of-order scope disposal.
Using BeginScopeAsync from helper methods
BeginScopeAsync initializes the scope asynchronously through a value factory. If you call it from a helper method, keep the helper synchronous and avoid await in the call. Otherwise new scope will not be propagated back to the caller. The value factory itself may use await.
private Task<IDisposable> BeginUnitOfWorkAsync(
ScopedAsyncLocal<IUnitOfWork> local,
CancellationToken cancellation = default) =>
local.BeginScopeAsync(
async () =>
{
// The body is simplified for demonstration purposes.
DbConnection? connection = null;
DbTransaction? transaction = null;
try
{
connection = await _connectionFactory.CreateConnectionAsync(cancellation);
await connection.OpenAsync(cancellation);
transaction = await connection.BeginTransactionAsync(cancellation);
return new UnitOfWork(connection, transaction);
}
catch (Exception ex)
{
if (transaction != null)
{
await transaction.DisposeAsync();
}
if (connection != null)
{
await connection.DisposeAsync();
}
throw;
}
});
Documentation
Check documentation for more details and examples.
| 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
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.3 | 93 | 7/12/2026 |