Implement async / await template for manually created WCF client proxies

Given this interface

[ServiceContract] public interface IProductService { [OperationContract] Product Get(int id); } 

I would like to manually (i.e. without using scvutil or Add Service Reference in VS) create a proxy server on the client side.

I do it as follows

 public class ProductService: IProductService { readonly ChannelFactory<IProductService> factory; public ProductService() { factory = new ChannelFactory<IProductService>("*"); } public Product Get(int id) { var channel = factory.CreateChannel(); return channel.Get(id); } } 

My problem is that I also want the version of this method to be used as asynchronous / waiting, only on the client side, the server side is still synchronous.

I want this to be a general solution , because I have many methods and services of this kind.

+6
source share
2 answers

If you use ChannelFactory to allow asynchronous wait, your interface should return Task or Task<T> .

This will force your server side to return the task as well, but you can do it synchronously with Task.CompletedTask and Task.FromResult if you insist on its synchronization (although why would you, if you have an option).

For instance:

 [ServiceContract] interface IProductService { [OperationContract] Task<Product> GetAsync(int id); } class ProductService : IProductService { ChannelFactory<IProductService> factory; public ProductService() { factory = new ChannelFactory<IProductService>("*"); } public Task<Product> GetAsync(int id) { var channel = factory.CreateChannel(); return channel.GetAsync(id); } } class ProductAPI : IProductService { public Task<Product> GetAsync(int id) => Task.FromResult(Get(id)) } 
+9
source

You can do this without changing the service itself. You can simply define a second interface containing asynchronous and Task returning versions of the methods and tagged [ServiceContract(Name = "NameOfTheIterfaceWhichIsActuallyExposedOnTheServer")]

In the above example, you define the second interface with the GetAsync() operation:

 [ServiceContract(Name = "IProductService")] public interface IProductServiceAsync { [OperationContract] Task<Product> GetAsync(int id); } 

and even if your service still implements and provides an IProductService , you can use ChannelFactory<IProductServiceAsync> to call it. As long as the method names match the GetFoo / GetFooAsync , everything will work. How Add Service Link in Visual Studio can generate you a link to an asynchronous service service to a synchronous service.

See Asynchronously invoking a synchronous WCF method using ChannelFactory for a more detailed explanation of how this works.

+1
source

All Articles