MrD at KookerellaLtd
MrD at KookerellaLtd

Reputation: 2797

Is the FSharp.Data XML type provider generative or not?

(previously "using type provider from C#")

This should be easy to answer, and the underlying issue has be asked before, but I'm slightly confused about it, having dug into it, there's something I'm missing.

The Xml type provider in https://fsharp.github.io/FSharp.Data/library/XmlProvider.html

is erased?

so the types in it can't be used from another assembly?

"Erasing Type Providers produce types that can only be consumed in the assembly or project they are generated from" (says the MS docs).

but if I define in one assembly this

module Xml

type Xml = FSharp.Data.XmlProvider<"""
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>""">

let foo () = Xml.Parse ("")

and in another assembly, reference the above assembly and go...

let x = Xml.foo ()
let s = x.From

this compiles...so if the MS docs are correct, the provider must be generative?

if I implement the same code in C#,

var x = Xml.foo();
var y = x.From;

then this code doesnt compiler

'XmlElement' does not contain a definition for 'From' and no accessible extension method 'From' accepting a first argument of type 'XmlElement'

which seems to imply its erased...or I need to do something else (I've included the same dependencies).

My hunch is its erased, but then how does the F# assembly compile?

(I want it to be generative to use from C# and VB).

Upvotes: 1

Views: 304

Answers (2)

Scott Hutchinson
Scott Hutchinson

Reputation: 1721

As far as I can tell by looking at the source code, all the types provided by FSharp.Data are erased.

The XmlProvider type is defined by this line at https://github.com/fsharp/FSharp.Data/blob/master/src/Xml/XmlProvider.fs#L26

let xmlProvTy = ProvidedTypeDefinition(asm, ns, "XmlProvider", None, hideObjectMethods=true, nonNullable=true)

As you can see, the instantiation of the ProvidedTypeDefinition type does not include isErased=false.

The ProvidedTypeDefinition type has two constructors. See the signatures at https://github.com/fsprojects/FSharp.TypeProviders.SDK/blob/master/src/ProvidedTypes.fsi#L268-L275

Both constructors have an implementation including this line, which means that the provide type is erased by default:

let isErased = defaultArg isErased true

Without redesigning the XmlProvider, the only way you can consume it from C# is to wrap it in an F# class that exposes C#-friendly types. Not sure if that would result in a better design than just avoiding the type provider altogether.

Upvotes: 1

masoodahm
masoodahm

Reputation: 305

Assuming by "erased" you mean being removed from the FSharp.Data Library? then XMLProvider its probably not removed from it because I just tried your code and it works in F# project (as you have also noticed).

Now about the C# project the thing is TypeProviders are a Fsharp specific thing, whatever magic F# compiler is doing to type check xml and access the From xml-node here is probably only exclusive to F#.

The type of you variable x here is FSharp.Data.Runtime.BaseTypes.XmlElement, looking at the documentation here and the source code here.

There doesn't seem to be any way of accessing the xml nodes in an OOP way. Its probably not meant to be accessed that way either. If you want to parse xml and read its nodes in C# there are plenty of other ways for that. One being XmlReader in System.Xml

Upvotes: 0

Related Questions