2010-01-13

List Transactional WCF Bindings in F#

Scott Seely just posted how “F# is Changing My Style”.  He gave example code of how he now approaches coding in C# in a more functional way.  The code uses LINQ to print a list of WCF binding that have a default constructor and support transactions.  I think it actually is a whole lot more readable in F#:

open System
open System.ServiceModel
open System.ServiceModel.Channels
 
let hasDefaultConstructor (t:Type) =
  t.GetConstructors()
  |> Seq.exists(fun c -> c.GetParameters().Length = 0)
 
let getType (o:Object) =
  o.GetType()
 
let isTransactional (b:Binding) =
  b.CreateBindingElements()
  |> Seq.map getType
  |> Seq.exists typeof<TransactionFlowBindingElement>.Equals
 
let main() =
  typeof<Binding>.Assembly.GetTypes()
  |> Seq.filter typeof<Binding>.IsAssignableFrom
  |> Seq.filter hasDefaultConstructor
  |> Seq.map Activator.CreateInstance
  |> Seq.cast<Binding>
  |> Seq.filter isTransactional
  |> Seq.iter(printfn "%A")
 
  Console.ReadKey(false) |> ignore
  ()
 
main()

I built up the sequence a line or two at a time, printing the results as I went, then piping them to the next filter.  Simply comment out a few lines and you can print out all types in the assembly, all Binding types, or only those with default constructors.  It also feels a lot more reusable.  For example, hasDefaultConstructor is a function I can use elsewhere.

I do get the same answer as him as long as I use .NET 4:

System.ServiceModel.NetTcpBinding
System.ServiceModel.NetTcpContextBinding
System.ServiceModel.WSHttpBinding
System.ServiceModel.WSHttpContextBinding
System.ServiceModel.NetNamedPipeBinding
System.ServiceModel.WSFederationHttpBinding
System.ServiceModel.WS2007FederationHttpBinding
System.ServiceModel.WS2007HttpBinding
System.ServiceModel.WSDualHttpBinding

It looks like in .NET 3.5, NetTcpContextBinding and WsHttpContextBinding are in System.WorkflowServices.dll, but they are included in System.ServiceModel.dll in .NET 4.