Question

Is there an equivalent to the F# TypeProvider in C#? I am looking at the easiest way to read an Xml file with C#. At this point I am planning to use XDocument, but I was wondering if there was something better.

F# makes it so easy to read an Xml file that I wonder if I shouldn't switch language for Xml processing!

Était-ce utile?

La solution

As already mentioned, C# does not support type providers and there is no easy way for emulating them (as Gustavo mentioned, you could use generated type providers through a small F# library, but XML, JSON, CSV and others are not this kind.)

I think using F# library that does the processing is the best approach.

A more complicated alternative would be to write code that lets you define types to model the XML file in C# and then automatically reads the file into these classes. I do not think anything like this exists, but I wrote a similar thing in F# (before type providers), so you can see the snippet for inspiration. The usage looks like this:

// Modelling RSS feeds - the following types define the structure of the
// expected XML file. The StructuralXml parser can automatically read
// XML file into a structure formed by these types.
type Title = Title of string
type Link = Link of string
type Description = Description of string

type Item = Item of Title * Link * Description
type Channel = Channel of Title * Link * Description * list<Item>
type Rss = Rss of Channel

// Load data and specify that names in XML are all lowercase
let url = "http://feeds.guardian.co.uk/theguardian/world/rss"
let doc : StructuralXml<Rss> = 
  StructuralXml.Load(url, LowerCase = true)

// Match the data against a type modeling the RSS feed structure
let (Rss(channel)) = doc.Root
let (Channel(_, _, _, items)) = channel
for (Item(Title t, _, _)) in items do
  printfn "%s" t

Autres conseils

Is there any reason why you can't add an F# library to your solution? That project can create the abstraction over the XML that you want, and you could consume it from your C# projects.

No, it's not possible to use type providers directly in C#.

For generated type providers, you can "instantiate" the type provider in a F# project, and then use that from C#, but that doesn't work for erased type providers like CsvProvider, JsonProvider, XmlProvider, Freebase or Worldbank. (It will work for the builtin SqlProvider and WsdlProvider, though).

There has been some discussion of switching CsvProvider, JsonProvider and XmlProvider to the generated model so they're usable for data-binding in C# (https://github.com/fsharp/FSharp.Data/issues/134#issuecomment-20104995), but that will probably take a while to happen.

My suggestion is to either swtich to F# altogether, or create record types that mirror the types that the type provider creates. Example:

type T = {
    A : int
    B : string
    (...)
}

type XmlT = XmlProvider<"xml file">

let getXml() =
    let xml = XmlT.GetSample()
    { A = xml.A
      B = xml.B
      (...) }

I took a look at your link to the XmlProvider in F# and I have not seen anything like it in C#. I use C# with Xml quite alot and often use XDocument and XElement to load and parse Xml with. Once I have Xml loaded into the XDocument I use Linq to Xml to perform similar things. I often use Linq Pad for general queries into the Xml which works well with C# not sure about F# though.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top