Normalizing Service Proxies

If you have multiple services that share data contracts, and you generated proxies (Add Service Reference) for those services, you end up with multiple copies of the same object on the client.

For example: BluRayFriend has a Review service and a Product service. The product service, obviously, deals with Products. The Review services, less obviously, does return a product when you look up a Review. The review is for a given product.

That’s two service references, so on the client, two Product objects are created:

  1. Client.ReviewService.Product
  2. Client.ProductService.Product

They have nothing in common. I’ve tried various approaches to have it figure out it’s the same object and reuse it, but no luck. The simple fact is that when you create the service references, it asks you for a namespace, and it must be a new namespace.

BluRayFriend also has a STAR RATING control. When I was using the contracts directly (as opposed to the generated proxies), the star control accepted a PRODUCT as a parameter. Once I switched to the contracts, that no longer worked. Sometimes the Product comes from the Review service, and other times it’s from the Product service. One has nothing to do with the other.

So how can you take two different product objects and treat them as if they’re the same type of object without altering the generated code? (If you alter the generated code, then regenerate, your alterations are lost).

This can be done quite easily via partial classes.

  1. Create an IProduct interface
  2. Use partial classes to extend the generated proxies, and have them implement IProduct.
  3. Change the Star Rating control to accept an IProduct.

I accomplish steps 1 and 2 in a single file. As long as the extensions are just a few lines each, it’s nice to be able to go to one place and see them all. That’s an exception to a rule I’m usually very passionate about: one thing per file, even if the thing is a 4 line Enum. But, in this case, I like seeing them all at once.

ContractNormalization.cs

namespace BluRayFriend.ServicesClient.ProductService
{
  
public partial class Product : IProduct
  
{
   }
}

namespace BluRayFriend.ServicesClient.ReviewService
{
  
public partial class Product : IProduct
  
{
   }
}

It gets more complicated when dealing with collections. I don’t have an example handy, but roughly: If there’s a method called GetProducts() that returns an array of Products, then you have to extend the client proxy. You add a new method called GetIProducts(). It calls GetProducts(), then converts the result to an array of IProduct.

It works, but I find it obnoxious. It would be nice if the we had the option to generate proxies that recognized common data types across services. The more methods you add, and the more complex types you have (IE: multiple review objects containing product objects), the more complicated it becomes. The result is a nicer client API, though, which is good.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: