Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expose types generated by an F# Type Provider to C# and XAML

So, I'm using the XML Type Provider to create types from an XML document.

One of the elements in the XML file has a Date property:

<Edit Date="06/30/2015 16:57:46"
      ... />

Which of course results in a Type like this:

type Edit = 
    inherit XmlElement

    member Date:  DateTime
    ...

Is there a way that I can add the following code:

 member this.LocalTime
    with get() =
        this.Date.ToLocalTime()

To the resulting Edit type?

The reason for this is that I'm binding to instances of Edit from XAML and I really don't want to write an IValueConverter just to do that.

Edit:

So, I just realized that these types do not make it to my XAML. Instead, I get instances of FSharp.Data.Runtime.BaseTypes.XmlElement which of course do not even contain the properties I see in F# code. I also need to consume these types from C# code, and even there I get only XmlElements without the properties

I know I could use XPath in XAML to navigate the XElements inside this, but I still need a way to access the resulting object model in a strongly typed way, both from C# and XAML.

Edit2:

So now I wrote a Type Extension like this:

type Catalog.Edit with
    member this.LocalTime with get() = this.Date.ToLocalTime()

And I see the member in F# code just like the generated members. However there's 2 drawbacks to this approach:

1 - It forced me to change my namespace into a module, which is less convenient since these types are all consumed from C# code and in there I see them as nested classes into the module class, which is ugly.

2 - I still can't see this member (nor the generated ones) from either C# nor XAML.

What's the correct way to implement this in the described scenario?

like image 865
Federico Berasategui Avatar asked Jul 22 '15 14:07

Federico Berasategui


People also ask

How do you publish types?

Publish to @typesPackages under the @types organization are published automatically from DefinitelyTyped using the types-publisher tool. To get your declarations published as an @types package, please submit a pull request to DefinitelyTyped.

Can I import a TypeScript into JavaScript?

Importing TypeScript files dynamically into JavaScript requires additional compilation step, which is troublesome to write for many. Popular typescript-require package seems to be obsolete and doesn't allow much customization.


1 Answers

The F# Data type providers for XML and JSON are erasing type providers. This means that the types you see when you use them from F# do not actually exist at runtime - they are replaced with some underlying runtime representation (here XmlElement).

Unfortunately, this means that the types are not real types and so they are only visible to F#.

My recommendation is to define a simple domain type using F# records and load your data from the XML into your records. This is a bit more work, but it also gives you a bit more safety, because you are explicitly defining the structure - and so if your XML changes, you'll know you need to change your XAML code too!

It should be as easy as something like this:

type Edit = { Date : DateTime }

let GetData () = 
  let doc = MyXmlType.Load("somefile.xml")
  seq { for item in doc.Edits -> { Date = item.Date } }
like image 104
Tomas Petricek Avatar answered Nov 15 '22 06:11

Tomas Petricek