【发布时间】:2016-10-12 11:36:57
【问题描述】:
我正在尝试使用XmlProvider 来解析一些非常大的数据文件(大约 50 MB)。由于它们太大,使用真实的数据文件作为样本是不切实际的,所以我创建了一个样本 XML 文件,我希望是可用数据的代表性样本。但是,我不能 100% 确定我已经涵盖了该 50 兆字节文件中的所有可能元素,因此我试图验证我的样本是否具有代表性。我正在尝试使用反射来帮助进行验证,但我遇到了问题。
首先,背景。我不确定的原因是因为我正在解析的 XML 文件本质上具有以下(非常扁平的)数据结构:
<root-element>
<object class="Foo" guid="Guid001">
<color>Brown</color>
<shape>Square</shape>
<children>
<childRef guid="Guid003" />
</children>
</object>
<object class="Bar" guid="Guid002">
<firstName>John</firstName>
<lastName>Smith</lastName>
</object>
<object class="Quux" guid="Guid003" parentGuid="Guid001">
<secondaryColor>Maroon</secondaryColor>
<stroke>Dashed</stroke>
<shape>Circle</shape>
</object>
<object class="Quux" guid="Guid004">
<color>Blue</color>
<stroke>Dotted</stroke>
<shape>Hexagon</shape>
</object>
</root-element>
(在真实的数据文件中,“Guid001”等是真实的 GUID;但对于这个虚构的例子,我保持简单。)
基本上,它是一个包含大量object 元素的平面数据文件,每个元素都指向该数据来自程序中的一个C# 类实例。这些元素半随机地混合在一起,在同一个数据文件中表示了几个不同的类族。 (这就是为什么我的虚构数据文件将绘图形状与人员记录混合在一起的原因——我正在使用的真实数据文件在单个文件中具有类似的关注点。)
正如我所说,我为我的代表性样本或多或少随机选择了一堆记录。我已经尝试从每个类中至少选择一个,以便涵盖大多数属性名称,但是如果(例如)我最终为 Quux 类选择 Guid004 而不是 Guid003,该怎么办?然后我提供的类型实际上不会知道 SecondaryColor 属性。我想我可以在我提供的类型上使用.GetType(),然后调用.GetProperties() 来获取我提供的类型认为它知道的所有属性的列表。但是当我这样做时:
let firstObject = rootElement.Objects[0]
printfn "%A" firstObject.GetType().GetProperties()
正如我所期望的,我得到的只是两个属性,而不是得到一个名为Color、Shape、Children、FirstName 等的属性列表, XElement 和 _Print。
我想,我可以遍历我真实数据中的所有XElements,并将它们的一组子元素名称放在一起。然后从我的样本数据中取出一组子元素名称,并比较两组。如果这两个集合相等(例如,它们之间的差异是空集合),那么我就会知道我已经覆盖了样本数据中的所有基础。
但是,我使用 XmlProvider 正是因为我不想处理XElement 的麻烦及其怪癖(如XNames everywhere instead of strings 等)。我知道检索 XmlProvider 提供的类型的有效属性列表是可能的,因为 Atom 中的自动完成下拉列表(通过 Ionide)正是为我提供了:所有有效属性的列表。但标准的 .Net 反射方法在应用于 XmlProvider 提供的类型时似乎并没有达到我的预期。
因此,既然反射似乎没有按照我的预期进行,我应该如何获取 XmlProvider 为我的类型创建的有效属性列表?
【问题讨论】:
标签: xml f# type-providers