Saturday, November 8, 2008

Linq to XML in F#

Last week in the entry titled "Mocking F#", we walked through the creation of a customer service implementation in F# and explored how a dynamic mock object framework can be used to help quickly drive development with tests. In that entry, we implemented a DAO (Data Access Object) that simply creates a dummy customer class . This blog entry will focus on adding functionality to that CustomerDao class so that it retrieves the data from an XML file using Linq to XML.

First, Add References:

The first step that we must do is add a reference to System.Xml and System.Xml.Linq in both the test project and the F# project.

The C# Tests:

The goal of these tests is to verify that a specific customer can be retrieved from the XML source.  Method "CanGetCustomerById" retrieves the customer from the actual XML source (which in this case is hard coded into the GetById member, but could have easily been retrieved from a file or database).  Method "CanGetCustomerByIdWithXmlProvided" creates a fake XElement and passes it to the function for test purposes.

        
[TestMethod]
public void CanGetCustomerById()
{
    FSharpMockExample.Data.ICustomerDao customerDao = new  FSharpMockExample.Data.CustomerDao();
    FSharpMockExample.Entities.ICustomer customer = customerDao.GetById(1);
    Assert.AreEqual(customer.Id, 1);
    Assert.AreEqual(customer.Name, "ABC Company");
    Assert.AreEqual(customer.Balance, 20);
}

[TestMethod]
public void CanGetCustomerByIdWithXmlProvided()
{
    XElement xElement =
        new XElement("c",
            new XElement("Customer",
                new XAttribute("Id", "1"),
                new XAttribute("Name", "ABC Company"),
                new XAttribute("Balance", "20.00")),
            new XElement("Customer",
                new XAttribute("Id", "2"),
                new XAttribute("Name", "AABB, Inc"),
                new XAttribute("Balance", "30.00")));
    FSharpMockExample.Data.ICustomerDao customerDao = new FSharpMockExample.Data.CustomerDao();
    FSharpMockExample.Entities.ICustomer customer = customerDao.GetById(xElement, 2);
    Assert.AreEqual(customer.Id, 2);
    Assert.AreEqual(customer.Name, "AABB, Inc");
    Assert.AreEqual(customer.Balance, 30);
}

The F# Signature File:

The signature file looks very similar to that which was created during the last entry. The main difference is a new overloaded GetById function, which contains a tuple (a tuple is common F# data structure used to group data types) of type "XElement * int". Since XElement is used, we must also open System.Xml.Linq.

#light
namespace FSharpMockExample.Data
open FSharpMockExample.Entities
open System.Xml.Linq

type ICustomerDao = interface
    abstract GetById: int -> ICustomer
    abstract GetById: XElement * int -> ICustomer
end

type CustomerDao = class
    new: unit -> CustomerDao
    interface ICustomerDao
end

The F# Source File:

Most of the changes are found in this file.  The first thing that an astute reader might notice is the XLinqHelper module.  Modules provide a way to group and reuse identifiers and functions.  The CustomerDao class encapsulates the majority of the changes.  Member GetById xml retrieves, and in this sample actually creates, the source xml.  It then casts the current class to the ICustomerDao interface, parses the raw xml into an XElement and calls the overloaded GetById XElement*int member.  The overloaded GetById XElement*int member uses the Seq library to find the customer by the specified CustomerId, news up a customer object, casts it to an ICustomer, and finally returns the result.

#light
namespace FSharpMockExample.Data
open FSharpMockExample.Entities
open System.Xml.Linq

module XLinqHelper = 
    let GetXName xname = XName.op_Implicit(xname)

type ICustomerDao = interface
    abstract GetById: int -> ICustomer
    abstract GetById: XElement * int -> ICustomer
end

type CustomerDao = class
    new()={}
    interface ICustomerDao with
        member this.GetById id =
            let rawXml = "<Customers>
                              <Customer Id=\"1\" Name=\"ABC Company\" Balance=\"20.00\"/>
                              <Customer Id=\"2\" Name=\"AABB, Inc\" Balance=\"30.00\"/>
                          </Customers>"
            let thisInterface = (this :> ICustomerDao)
            let xml = XElement.Parse rawXml
            thisInterface.GetById (xml, id)

        member this.GetById (xml, id) =
            let GetCustomer (customerElement:XElement) = 
                new Customer(int(customerElement.Attribute(XLinqHelper.GetXName "Id").Value), 
                    customerElement.Attribute(XLinqHelper.GetXName "Name").Value, 
                    decimal(customerElement.Attribute(XLinqHelper.GetXName "Balance").Value)) :> ICustomer

            xml.Elements() |> Seq.find(fun customer -> (int(customer.Attribute(XLinqHelper.GetXName "Id").Value) = id)) 
                           |> GetCustomer
end

Conclusion:

As you can see from the example, adding basic data access functionality using Linq to XML is pretty easy.  With the help of the Seq library and System.Xml.Linq, the possibilities of XML data manipulation are endless. 

A special thanks goes out to Elijah Manor for adding F# support to Syntax Higherlighter.  Very cool Elijah!!

4 comments:

  1. [url=http://tinyurl.com/getvpn][b]Click here to get VPN service![/b][/url]

    [b]Anonymous surfing[/b]
    Using our service you'll be fully anonymous in the Internet. Hide your IP address, and nobody will know that strange visitor from Germany ( Great Britain, Estonia and so ), is you.

    [b]Full access to network[/b]
    You can use any services, access any sites and use any software with us. BitTorrent, Skype, Facebook, MySpace, Twitter, Pocker .. we have no restrictions.

    [b]Traffic protection[/b]
    Don't worry, from this moment all you data will be protected using 256 bit Blowfish encryption algorithm. Nobody can access your internet data.

    [b]Wide variety of countries[/b]
    You can choose one of over twenty high speed servers located in different parts of the world, from South America coast to islands in Indian Ocean.

    Related keywords:
    anonymous surfing review
    proxy server vpn
    anonymous secure surfing
    proxy vpn
    anonymous vpn free
    internet explorer vpn
    vpn dial up
    ssl vpn
    Traffic protection
    anonymous surfing freeware
    anonymous surfing software
    vtunnel
    anonymous surfing vpn
    best anonymous browser
    surf the web anonymous
    best anonymous surfing
    anonymizer anonymous surfing review
    firefox anonymous surfing
    Virtual Private Networks
    Free Vpn Client Software
    anonymous surfing software
    [url=http://dasbmw.ru] anonymous surfing software[/url]
    [url=http://seobraincenter.ru] anonymous proxy[/url]
    [url=http://carlwebster.com/members/Alexander-Pwnz.aspx]Buy Cheap Zoloft[/url]

    ReplyDelete
  2. [url=http://tinyurl.com/getvpn][b]Click here to get VPN service![/b][/url]

    [b]Anonymous surfing[/b]
    Using our service you'll be fully anonymous in the Internet. Hide your IP address, and nobody will know that strange visitor from Germany ( Great Britain, Estonia and so ), is you.

    [b]Full access to network[/b]
    You can use any services, access any sites and use any software with us. BitTorrent, Skype, Facebook, MySpace, Twitter, Pocker .. we have no restrictions.

    [b]Traffic protection[/b]
    Don't worry, from this moment all you data will be protected using 256 bit Blowfish encryption algorithm. Nobody can access your internet data.

    [b]Wide variety of countries[/b]
    You can choose one of over twenty high speed servers located in different parts of the world, from South America coast to islands in Indian Ocean.

    Related keywords:
    anonymous surfing review
    proxy server vpn
    anonymous secure surfing
    proxy vpn
    anonymous vpn free
    internet explorer vpn
    vpn dial up
    ssl vpn
    Traffic protection
    anonymous surfing freeware
    anonymous surfing software
    vtunnel
    anonymous surfing vpn
    best anonymous browser
    surf the web anonymous
    best anonymous surfing
    anonymizer anonymous surfing review
    firefox anonymous surfing
    Virtual Private Networks
    Free Vpn Client Software
    anonymous surfing software
    [url=http://dasbmw.ru] anonymous surfing software[/url]
    [url=http://seobraincenter.ru] anonymous proxy[/url]
    [url=http://carlwebster.com/members/Alexander-Pwnz.aspx]Buy Cheap Zoloft[/url]

    ReplyDelete
  3. greetings to all.
    I would first like to thank the writers of this blog by sharing information, a few years ago I read a book called Real Estate Investment costa rica in this book deal with questions like this one.

    ReplyDelete
  4. Hello .. firstly I would like to send greetings to all readers. After this, I recognize the content so interesting about this article. For me personally I liked all the information. I would like to know of cases like this more often. In my personal experience I might mention a book called Generic Viagra in this book that I mentioned have very interesting topics, and also you have much to do with the main theme of this article.

    ReplyDelete