You can automatically generate a new interface containing asynchronous versions of methods from the source interface using T4 and use it in ChannelFactory without changing the server-side interface .
I used NRefactory to parse the original and generate new C # source code and AssemblyReferences.tt to use the nuget packages in the T4 template:
<#@ template debug="false" hostspecific="true" language="C#" #> <#@ include file="AssemblyReferences.tt" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="ICSharpCode.NRefactory.CSharp" #> <#@ output extension=".cs"#> <# var file = System.IO.File.ReadAllText(this.Host.ResolvePath("IUserService.cs")); if(!file.Contains("using System.Threading.Tasks;")) { #> using System.Threading.Tasks; <# } #> <# CSharpParser parser = new CSharpParser(); var syntaxTree = parser.Parse(file); foreach (var namespaceDeclaration in syntaxTree.Descendants.OfType<NamespaceDeclaration>()) { namespaceDeclaration.Name += ".Client"; } foreach (var methodDeclaration in syntaxTree.Descendants.OfType<MethodDeclaration>()) { if (methodDeclaration.Name.Contains("Async")) continue; MethodDeclaration asyncMethod = methodDeclaration.Clone() as MethodDeclaration; asyncMethod.Name += "Async"; if (asyncMethod.ReturnType.ToString() == "void") asyncMethod.ReturnType = new SimpleType("Task"); else asyncMethod.ReturnType = new SimpleType("Task", typeArguments: asyncMethod.ReturnType.Clone()); methodDeclaration.Parent.AddChild(asyncMethod, Roles.TypeMemberRole); } #> <#=syntaxTree.ToString()#>โ
You pass the interface file name to the template:
using System.Collections.Generic; using System.ServiceModel; namespace MyProject { [ServiceContract] interface IUserService { [OperationContract] List<User> GetAllUsers(); } }
To get a new one:
using System.Threading.Tasks; using System.Collections.Generic; using System.ServiceModel; namespace MyProject.Client { [ServiceContract] interface IUserService { [OperationContract] List<User> GetAllUsers (); [OperationContract] Task<List<User>> GetAllUsersAsync (); } }
Now you can put it in a factory to use the channel asynchronously:
var factory = new ChannelFactory<MyProject.Client.IUserService>("*"); var channel = factory.CreateChannel(); var users = await channel.GetAllUsersAsync();
source share