-
Notifications
You must be signed in to change notification settings - Fork 21
AsyncRewriter
Shaolinq.AsynRewriter automatically converts your sync methods into async methods using the Roslyn compiler to parse and generate equivalent async code. Library developers quickly realise that the code for async is pretty much the same as their sync code except that calls to Method1() are replaced with await Method1Async() calls which results in a lot of copy & paste code. Shaolinq.AsyncRewriter solves this issue by generating the code for you.
- Source based so does not require shipping dependent assemblies
- Supports rewriting interface and abstract methods
- Supports matching asynchronous methods from extension methods
- Supports methods with
params - Supports methods with expression bodies
- Supports generating async methods with different method visibility from the source method
- Gives warnings/hints if you have manually written async methods that don't use async versions of methods when they are available.
Shaolinq.AsyncRewriter is available as a NuGet package (Shaolinq.AsyncRewriter). Create a new class library project and then add the Shaolinq.AsyncRewriter NuGet Package. The package will automatically add some pre-build steps to your csproj to generate the async code before the full compile. Additionally the package will add a class named RewriteAsyncAttribute to your project. Simply decorate any method in your project with the [RewriteAsync] attribute to have an equivalent async method generated. You will need to make sure any types containing [RewriteAsync] are declared as partial because AsyncRewriter will add async methods to the type by outputting a matching partial classes.
AsyncRewriter will generate a source file named GeneratedAsync.cs. All types with methods attributed with [RewriteAsync] will get equivalent async methods (two async methods for each sync method) outputted into GeneratedAsync.cs.
All methods are translated as follows:
- For each attributed sync method two methods are generated with the name and "Async" appended. One is a method that takes a
CancellationTokenand one that does not. TheCancellationTokenparameter is inserted after the last non-default and non-params parameter - For all method bodies of generated async methods, method calls are replaced with
awaitasynchronous calls if one is available. - Both static and instance methods are replaced with asynchronous versions where possible.
Candidate async methods for synchronous method calls are chosen from the following set:
- An async version of the method automatically generated by AsyncRewriter because the method was attributed with
[RewriteAsync] - An manually written async version of the method - defined by a method with the same name and
Asyncsuffix. If aCancellationTokenversion of the method is defined then it is preferred. - An extension method is available that matches the name and signature of the instance method being called.
Source:
[RewriteAsync]
public virtual IDbConnection OpenServerConnection()
{
if (this.dbProviderFactory == null)
{
this.dbProviderFactory = this.CreateDbProviderFactory();
}
var retval = this.dbProviderFactory.CreateConnection();
retval.ConnectionString = this.ServerConnectionString;
retval.Open();
return retval;
}Generated code:
public virtual Task<IDbConnection> OpenServerConnectionAsync()
{
return this.OpenServerConnectionAsync(CancellationToken.None);
}
public virtual async Task<IDbConnection> OpenServerConnectionAsync(CancellationToken cancellationToken)
{
if (this.dbProviderFactory == null)
{
this.dbProviderFactory = this.CreateDbProviderFactory();
}
var retval = this.dbProviderFactory.CreateConnection();
retval.ConnectionString = this.ServerConnectionString;
await retval.OpenAsync(cancellationToken).ConfigureAwait(false);
return retval;
}Source:
public partial interface Foo
{
[RewriteAsync]
string Bar(int param, params string[] args);
}Generated code:
public partial interface Foo
{
Task<string> BarAsync(int arg1, params string[] args);
Task<string> BarAsync(int arg1, CancellationToken cancellationToken, params string[] args);
}Copyright (c) 2018 Thong Nguyen (tumtumtum@gmail.com)