puffpio [dot] com

puffpio [dot] com

David Pio  //  software developer, technology geek, gadget whore, motorsports junkie, video game nerd, partner engineer at Facebook

Nov 10 / 12:29am

What I want for asynchronous WCF clients and C#5 async/await

I have a problem with Adding a Service Reference (and thus using svcutil). It generates proxy interfaces and proxy datatypes. If my WCF service used custom datatypes, the service reference would create a proxy datatype for it. This gives me headaches because I think I have a type Foo when in fact I have a proxied version. Now I have to cast between them. Also, if I have added two service references and they used the same datatype, guess what? It will generate two different proxied datatypes. And if I change anything about the service or the datatypes, I need to regenerate the service reference. What a pain.

Instead, I do something like this:

 [ServiceContract]
 public interface IContract
 {
   [OperationContract]
   int Add(int a, int b);
 }
 
 public class MyClient : ClientBase<IContract>, IContract
 {
   public int Add(int a, int b) { return base.Channel.Add(a, b); }
 }
 

Nice and clean huh? The WCF client uses the same interface and same datatypes as the service so no need to regenerate service references. It's tightly coupled and I also get compile time errors if I change the service interface. The only problem is that doing it this way does not generate asynchronous client methods.

The Visual Studio Async CTP gives a sneak preview into the future of the language. It adds two new keywords async and await which make it dead simple to convert regular code into asychronous code. I won't go into detail on how it works, but in addition to the language/compiler changes it also includes a bunch of extension methods that add this new style of asynchronous access to a bunch of preexisting classes that have asynchronous methods. For example, TextWriter contains a synchronous Write() as well as the asynchronous BeginWrite() and EndWrite(). This CTP adds WriteAsync() which wraps the BeginWrite() and EndWrite() into this new async/await syntax. What I envision, and what I hope happens is that they also do some work on WCF client generation (hopefully not using svcutil, but extending ClientBase). I want there to be something like this:

 [ServiceContract]
public interface IContract
{
   [OperationContract]
   int Add(int a, int b);
}

public class MyAsyncClient : AsyncClientBase<IContract>, IAsyncContract<IContract>
{
   public async Task<int> AddAsync(int a, int b) { return await base.AsyncChannel.AddAsync(a, b); }
}

That's my pipe dream. I want to not have to generate proxy interfaces and datatypes, retain compile time errors when the interface changes, and not use svcutil. The IAsyncContract<T> would be enforced to take an interface that is marked as a ServiceContract. It would then take all the methods in the interface marked as an OperationContract and create a new interface with them, but changing their return types from what they were originally (e.g. int, string, List<double>, etc) to async Tasks (e.g. Task<int>, Task<string>, Task<List<double>>).

Right now I think it's impossible for an interface like IAsyncContract to exist and do what I would like, but maybe some kind of autogenerated code could take place on compile could net similar results. Thoughts?