Wednesday, December 23, 2009

Relearning WCF

Of late I have been playing with WCF again. We have some projects here at work that require some integration and we are desperately trying to move away from the old ASMX based services. Unfortunately because I have not touched WCF the whole time I have been here (12 months now, wow! That has gone fast!) and I have found myself at a point where I really need to relook at WCF again and basically relearn it... oh well.
Anyway here is a bunch of stuff that here, that at work we have found to be useful that you may not otherwise be able to do with ASMX or may not be aware you could do with WCF.

IOC and WCF


You can in fact use IoC with WCF, there are some good blog posts and accompanying videos to show what to do and if, like me, you just want one ready to that uses the CSL then The Code Junkie has done it for you!


Dynamic KnownType Resolution


This always erked me that I had to put into the data contract that I knew of other types, it was like really bad tight coupling*. There are a bunch of way to declare known types with the bottom example seeemingly a little known alternative : a provider mechanism

in config


<system.runtime.serialization> <dataContractSerializer> <declaredTypes>...

Data contract with attributes


[KnownType(typeof(PurchaseApprovalRequest))]
[DataContract]
public class ApprovalRequest
{...

Knowntype provider


The way I have just found out is by declaring a knowntype provider on the service contract:

[ServiceKnownType("GetKnownTypes", typeof(ApprovalRequestKnownTypesProvider))]
[ServiceContract]
public interface IApprovalService
{...


with the following class (change the implementation to suit yourself, this is from some of my demo code, it’s not recommended!)

internal static class ApprovalRequestKnownTypesProvider
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
// collect and pass back the list of known types
foreach (var module in Assembly.GetExecutingAssembly().GetLoadedModules())
{
foreach (var knownType in module.FindTypes(
(t, f) => ((Type)f).IsAssignableFrom(t), typeof(ApprovalRequest)))
{
yield return knownType;
}
}
}
}

With these two little nuggets I have been able to produce a pretty handy little broker service that act as a very basic content based router that keeps the client messages very clean and does not expose any implementation details (i.e. no passing of service or workflow names in the message header!)

*NB: to paraphrase Krzysztof: "Polymorphism is an OO term, not SOA term, so I don't use it, and make my contracts explicit wherever possible." be wary that you are using known types for the right reasons