Zomp.SyncMethodGenerator
1.5.1
dotnet add package Zomp.SyncMethodGenerator --version 1.5.1
NuGet\Install-Package Zomp.SyncMethodGenerator -Version 1.5.1
<PackageReference Include="Zomp.SyncMethodGenerator" Version="1.5.1"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Zomp.SyncMethodGenerator" Version="1.5.1" />
<PackageReference Include="Zomp.SyncMethodGenerator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Zomp.SyncMethodGenerator --version 1.5.1
#r "nuget: Zomp.SyncMethodGenerator, 1.5.1"
#addin nuget:?package=Zomp.SyncMethodGenerator&version=1.5.1
#tool nuget:?package=Zomp.SyncMethodGenerator&version=1.5.1
Sync Method Generator
This .NET source generator produces a sync method from an async one.
⭐ Star this project if you hate code duplication or calling async methods from sync.
Use cases
- A library which exposes both sync and async version of a method
- An application has to process two kinds of data in the same way:
- Large data from I/O which cannot be stored in memory before processing: Original async method
- Small sample of data in memory, usually a sample of the larger data: Generated sync method
How it works
CreateSyncVersionAttribute on a method
Decorate your async method with CreateSyncVersionAttribute
in your partial
class, struct, record, or interface:
[Zomp.SyncMethodGenerator.CreateSyncVersion]
static async Task WriteAsync(ReadOnlyMemory<byte> buffer, Stream stream,
CancellationToken ct)
=> await stream.WriteAsync(buffer, ct).ConfigureAwait(true);
and it will generate a sync version of the method:
static void Write(ReadOnlySpan<byte> buffer, Stream stream)
=> stream.Write(buffer);
A list of changes applied to the new synchronized method:
Remove
async
modifierRemove
await
from methods as well asforeach
statementChange types
Remove parameters
- CancellationToken
- IProgress<T>, unless the
PreserveProgress
property is set totrue
.
Invocation changes
- Remove
ConfigureAwait
from Tasks and Asynchronous Enumerations - Remove
WaitAsync
from Tasks - Remove WithCancellation
- Rewrite asynchronous invocations with
Async
suffix to call synchronous version (e.g. MoveNextAsync() becomes MoveNext()) - Remove asynchronous invocations without the
Async
suffix - Remove CancellationToken parameter
- Remove IProgress<T>.Report(T) call
- Remove Memory<T>.Span property
- Change
await
Task<TResult>.FromResult(value
) tovalue
- Change
await
Task.Delay(value
) to Thread.Sleep(value
) - Change any invocation returning ConfiguredCancelableAsyncEnumerable<T> to IEnumerable.GetEnumerator()
- Remove
Remove
CreateSyncVersionAttribute
Update XML documentation
Properties
OmitNullableDirective
This source generator detects language version during the compilation. By default it will generate #nullable enable
directive if and only if the language version is 8 or above. Since it is impossible to reliably determine whether nullable context is turned on or not, OmitNullableDirective
property is available to omit that directive from generating.
[Zomp.SyncMethodGenerator.CreateSyncVersion(OmitNullableDirective = true)]
public async Task MethodAsync()
{
string f = null;
}
PreserveProgress
By default, this source generator removes IProgress<T>
parameters from async methods. To preserve them, use the PreserveProgress
option.
[Zomp.SyncMethodGenerator.CreateSyncVersion(PreserveProgress = true)]
public async Task MethodAsync(IProgress<double> progress)
{
progress.Report(0.0);
}
CreateSyncVersionAttribute on a type
You can also decorate your type (class, struct, record, or interface) to generate a sync version for every asynchronous method.
[Zomp.SyncMethodGenerator.CreateSyncVersion]
partial class MyClass {
async Task Method1Async(...) { ... }
async IAsyncEnumerable<...> Method2Async(...) { ... }
[Zomp.SyncMethodGenerator.SkipSyncVersion]
async Task WillNotGenerateAsync(...) { ... }
}
This will generate their sync counterparts:
[Zomp.SyncMethodGenerator.CreateSyncVersion]
partial class MyClass {
void Method1(...) { ... }
}
and
[Zomp.SyncMethodGenerator.CreateSyncVersion]
partial class MyClass {
IEnumerable<...> Method2(...) { ... }
}
SkipSyncVersionAttribute
To exclude a method from generating a sync version use SkipSyncVersionAttribute
on a method. See WillNotGenerateAsync
method in the example above.
SYNC_ONLY symbol
In case there is logic which should only be executed in the synchronized version of the method, wrap it in SYNC_ONLY
#if directive.
SYNC_ONLY
must not be defined anywhere. The source generator will scan #if directives for this symbol.
Code inside SYNC_ONLY
block will be copied as is. Unless global namespaces are used in the project, this code should contain fully qualified namespaces.
The following syntax:
[Zomp.SyncMethodGenerator.CreateSyncVersion]
public async Task WithSyncOnlyDirectiveAsync(CancellationToken ct)
{
#if SYNC_ONLY
System.Console.Write("Sync");
#endif
await Task.CompletedTask;
}
will output:
public void WithSyncOnlyDirective()
{
System.Console.Write("Sync");
}
If you only want to execute in the original async version, flip the flag like this: #if !SYNC_ONLY
.
Note: SYNC_ONLY
cannot be mixed with other symbols in a conditional expression and cannot have #elif
directive.
SYNC_ONLY
flag currently works in parameter lists, argument lists and statements.
Please always double check your code when using this flag.
If your use case is not supported, please log an issue.
Installation
To add the library use:
dotnet add package Zomp.SyncMethodGenerator
Development
Related projects
- SyncToAsyncExtension - Allows switching between sync and async versions of a method. Very useful in development of this library.
Act
This project is fully compatible with act.
Other than required packages to run act
itself, GitHub Actions script installs anything else that might be missing, such as node, yarn and dotnet. On Windows platform, software installation is performed on the host itself due to lack of container support.
To build the project using act follow these instructions:
Windows
Install chocolatey if missing.
Install the following packages if missing:
choco install git -y
choco install act-cli -y
refreshenv
In the project directory run:
act -P windows-latest=-self-hosted --artifact-server-path /tmp/artifacts
Linux
Install act by following these instructions.
In the project directory run:
act --artifact-server-path /tmp/artifacts
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- N.SourceGenerators.UnionTypes (>= 0.28.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (3)
Showing the top 3 popular GitHub repositories that depend on Zomp.SyncMethodGenerator:
Repository | Stars |
---|---|
FluentValidation/FluentValidation
A popular .NET validation library for building strongly-typed validation rules.
|
|
Zeugma440/atldotnet
Fully managed, portable and easy-to-use C# library to read and edit audio data and metadata (tags) from various audio formats, playlists and CUE sheets
|
|
AvionBlock/VoiceCraft
VoiceCraft software to implement proximity VC for Minecraft Bedrock Edition
|
Version | Downloads | Last Updated |
---|---|---|
1.5.1 | 0 | 6/29/2025 |
1.4.38 | 110 | 6/23/2025 |
1.4.37 | 184 | 6/23/2025 |
1.4.35 | 137 | 6/17/2025 |
1.4.32 | 219 | 6/17/2025 |
1.4.30 | 321 | 6/14/2025 |
1.4.29 | 502 | 6/12/2025 |
1.4.28 | 298 | 6/11/2025 |
1.4.27 | 279 | 6/11/2025 |
1.4.26 | 498 | 6/11/2025 |
1.4.25 | 499 | 6/10/2025 |
1.4.20 | 486 | 3/9/2025 |
1.4.18 | 182 | 2/24/2025 |
1.4.15 | 591 | 11/17/2024 |
1.4.14 | 1,690 | 8/7/2024 |
1.4.13 | 908 | 7/21/2024 |
1.4.11 | 725 | 7/15/2024 |
1.4.10 | 649 | 7/13/2024 |
1.4.8 | 305 | 7/8/2024 |
1.4.3 | 260 | 6/27/2024 |
1.4.1 | 290 | 5/21/2024 |
1.3.44 | 226 | 5/14/2024 |
1.3.43 | 304 | 4/26/2024 |
1.3.40 | 518 | 4/11/2024 |
1.3.39 | 262 | 4/9/2024 |
1.3.38 | 394 | 3/23/2024 |
1.3.36 | 228 | 3/20/2024 |
1.3.35 | 118 | 3/19/2024 |
1.3.33 | 182 | 3/18/2024 |
1.3.28 | 189 | 3/18/2024 |
1.3.27 | 208 | 3/17/2024 |
1.3.24 | 447 | 3/12/2024 |
1.3.23 | 249 | 3/12/2024 |
1.3.21 | 216 | 3/11/2024 |
1.3.20 | 247 | 3/11/2024 |
1.3.18 | 216 | 3/10/2024 |
1.3.17 | 290 | 2/26/2024 |
1.3.16 | 328 | 2/26/2024 |
1.3.13 | 239 | 2/25/2024 |
1.3.8-beta | 866 | 2/12/2024 |
1.3.6 | 304 | 1/26/2024 |
1.3.5 | 222 | 1/21/2024 |
1.3.1 | 321 | 1/17/2024 |
1.2.24 | 234 | 1/14/2024 |
1.2.18 | 204 | 1/5/2024 |
1.2.16 | 228 | 1/5/2024 |
1.2.13 | 206 | 1/4/2024 |
1.2.12 | 202 | 1/4/2024 |
1.2.8 | 205 | 1/3/2024 |
1.2.3 | 444 | 11/20/2023 |
1.2.1 | 215 | 11/13/2023 |
1.1.2 | 2,464 | 8/8/2023 |
1.0.14 | 289 | 8/4/2023 |
1.0.12 | 32,149 | 8/3/2023 |
1.0.11 | 259 | 8/2/2023 |
1.0.5 | 183 | 7/31/2023 |
1.0.3 | 168 | 7/29/2023 |
1.0.2 | 185 | 7/29/2023 |
1.0.1 | 274 | 7/27/2023 |
0.1.39-alpha | 543 | 1/25/2023 |
0.1.38-alpha | 267 | 1/19/2023 |
0.1.37-alpha | 265 | 1/19/2023 |
0.1.34-alpha | 255 | 1/18/2023 |
0.1.33-alpha | 235 | 1/15/2023 |
0.1.30-alpha | 296 | 11/21/2022 |
0.1.22-alpha | 249 | 11/19/2022 |
0.1.21-alpha | 249 | 11/19/2022 |
0.1.19-alpha | 224 | 11/19/2022 |
0.1.18-alpha | 258 | 11/18/2022 |
0.1.17-alpha | 329 | 11/14/2022 |
0.1.13-alpha | 235 | 11/13/2022 |
0.1.12-alpha | 276 | 10/31/2022 |
0.1.10-alpha | 233 | 10/28/2022 |
0.1.9-alpha | 276 | 10/27/2022 |
0.1.8-alpha | 298 | 10/27/2022 |
0.1.5-alpha | 253 | 10/27/2022 |
0.1.4-alpha | 277 | 10/27/2022 |
0.1.3-alpha | 304 | 10/26/2022 |
0.1.2-alpha | 300 | 10/25/2022 |
0.1.1-alpha | 324 | 10/25/2022 |