Geeks With Blogs
A Software Engineering Blog by Nick Holmes

I had half an hour to fill while I waited for a large download, on my slow connection. I'd thought about re-implementing my C# WCF test host in F#. It didn't look too complex, and indeed it wasn't:

#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\"
#r "System.ServiceModel.dll"
#r "Server.dll"
open System
open System.ServiceModel
open System.Diagnostics
open Coyote.FSWCFTest

let services =

    [ (typeof<TestWebService>, "http://localhost:8080/Test/FSWCFTest.svc") ]

let logException (msg, exn:Exception) =
    Trace.TraceWarning(msg)
    Trace.WriteLine(exn.Message)
    Trace.WriteLine(exn.Source)

let startHost (serviceType:Type, url) =
    try
        let uri = [| new Uri(url) |]
        let host = new ServiceHost(serviceType, uri)
        host.Open()
        Some(host)
    with
    | e -> logException ("Exception thrown starting service.", e)
           None

let stopHost (host: ServiceHost option)  =
    try
        match host with
        | None -> ()
        | Some(host) ->
            if host.State <> CommunicationState.Closed then
                host.Close()
                Trace.WriteLine("Service Stopped")               
    with
    | e -> logException ("Exception thrown stopping service.", e)

let showHostStatus (host: ServiceHost option) =
    match host with
    | Some(hst) ->
        let strdots = new String ( '.', 40 - hst.Description.Name.Length);
        Console.ForegroundColor <- match hst.State with
                                   | CommunicationState.Opened -> ConsoleColor.Green
                                   | _ -> ConsoleColor.Red        
        Console.WriteLine("{0} service{1}{2}", hst.Description.Name,

            strdots, hst.State.ToString())
    | None -> Console.ForegroundColor <- ConsoleColor.Red
              Console.WriteLine("Service failed to start.")

let main =
    Console.Title <- "Server Test Console"
    Console.BackgroundColor <- ConsoleColor.DarkBlue
    Console.WindowWidth <- 120
    Console.Clear()
    Console.WriteLine("Server Test Console")
    Console.WriteLine("Copyright 2008 Coyote Software, GmbH.")
    Console.WriteLine()
    let hosts = services |> List.map startHost
    let mutable quit = false
    while not quit do
        let inp = Console.ReadLine()  
        let inpClean = inp.Trim().ToLower()
        match inpClean with
        | "exit"   -> quit <- true
        | "cls"    -> Console.Clear()
        | "status" -> let cc = Console.ForegroundColor
                      Console.WriteLine("Status at {0} is", DateTime.Now)
                      hosts |> List.iter showHostStatus
                      Console.ForegroundColor <- cc      
        | "stop"   -> hosts |> List.iter stopHost
        | _        -> Console.WriteLine("Unknown command {0}", inp)
    done

This implementation is about half the size of the C# implementation, although the original has a couple of extra commands. I preferred Console.WriteLine to printfn, as I have used other Console methods, and I think the code is a little clearer.

One improvement to this app would be to have is use reflection to automatically find all  the services in the assembly (rather than require the list to be set up), but I've been using the C# version almost daily for over a year, and its good enough like this.

Posted on Tuesday, May 5, 2009 12:50 PM F# , Functional Programming | Back to top


Comments on this post: An WCF Service Host in F#

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Nick Holmes | Powered by: GeeksWithBlogs.net