所以,我正在使用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#代码中使用这些类型,即使在那里我只得到没有属性的XmlElement
我知道我可以在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#代码中消耗掉的,在那里我将它们视为嵌套类到模块类中,这很难看。
2 - 我仍然无法从C#或XAML中看到这个成员(也不是生成的成员)。
在描述的场景中实现这一点的正确方法是什么?
答案 0 :(得分:6)
XML和JSON的F#数据类型提供程序是擦除类型提供程序。这意味着从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 } }