如何将 F# 类型提供程序生成的类型公开给 C# 和 XAML

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

因此,我正在使用 XML Type Provider 从 XML 文档创建类型。

XML 文件中的一个元素具有 Date 属性:

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

这当然会导致这样的类型:

type Edit = 
    inherit XmlElement

    member Date:  DateTime
    ...

有什么方法可以添加以下代码:

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

到结果 Edit 类型?

原因是我从 XAML 绑定到 Edit 的实例,我真的不想为此写一个 IValueConverter

编辑:

所以,我才意识到这些类型不适合我的 XAML。相反,我得到了 FSharp.Data.Runtime.BaseTypes.XmlElement 的实例,它们当然甚至不包含我在 F# 代码中看到的属性。我还需要从 C# 代码中使用这些类型,即使在那里我也只得到 XmlElements 而没有属性

我知道我可以在 XAML 中使用 XPath 来导航其中的 XElements,但我仍然需要一种方法来以强类型方式访问生成的对象模型,无论是从 C# 还是 XAML.

编辑2:

所以现在我写了一个 Type Extension 这样的:

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

我在 F# 代码中看到的成员就像生成的成员一样。然而,这种方法有两个缺点:

1 - 它迫使我将我的 namespace 更改为 module,这不太方便,因为这些类型都是从 C# 代码中使用的,在那里我看到它们是嵌套的 classes 进入模块 class,这是丑陋的。

2 - 我仍然无法从 C# 或 XAML.

中看到此成员(也不是生成的成员)

在所描述的场景中实现此功能的正确方法是什么?

XML 和 JSON 的 F# 数据类型提供程序是 erasing 类型提供程序。这意味着您在 F# 中使用它们时看到的类型在运行时实际上并不存在 - 它们被替换为一些底层运行时表示(此处 XmlElement)。

不幸的是,这意味着这些类型不是 真正的 类型,因此它们仅对 F# 可见。

我的建议是使用 F# 记录定义一个简单的域类型,并将您的数据从 XML 加载到您的记录中。这需要做更多的工作,但它也给了你更多的安全性,因为你明确定义了结构——所以如果你的 XML 改变了,你就会知道你需要改变你的 XAML代码也是!

它应该像这样简单:

type Edit = { Date : DateTime }

let GetData () = 
  let doc = MyXmlType.Load("somefile.xml")
  seq { for item in doc.Edits -> { Date = item.Date } }