数据类型提供程序和反射:如何检查XmlProvider类型的属性



我正在尝试使用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#类实例,这些数据来自这些元素。图元是半随机混合在一起的,在同一数据文件中表示了几个不同的类族。(这就是为什么我虚构的数据文件将绘图形状与个人记录混合在一起的原因——我正在处理的真实数据文件在一个文件中也有类似的问题混合。)

正如我所说,我或多或少地随机选择了一堆记录作为我的代表性样本。我试着从每个类中至少选择一个,这样我就可以覆盖大多数属性名称,但如果(例如)我最终为Qoux类选择了Guid004而不是Guid003呢?那么我提供的类型实际上不知道SecondaryColor属性。我想我可以在我提供的类型上使用.GetType(),然后调用.GetProperties()来获得我提供的认为知道的所有属性的列表。但当我这样做时:

let firstObject = rootElement.Objects[0]
printfn "%A" firstObject.GetType().GetProperties()

与其像我所期望的那样得到一个名为ColorShapeChildrenFirstName等的属性列表,我得到的恰恰是两个属性,XElement_Print

我想,我可以迭代我的真实数据中的所有XElement,并将它们的一组子元素名称放在一起。然后从我的示例数据中获取子元素名称集,并比较这两个集。如果这两个集合相等(例如,它们之间的差是空集),那么我就知道我已经在样本数据中覆盖了所有的基。

然而,我之所以使用XmlProvider,正是因为我不想处理XElement及其怪癖(比如到处都是XName而不是字符串等等)的麻烦。我知道检索XmlProvider提供的类型的有效属性列表是可能的,因为Atom中的自动完成下拉列表(通过Ionide)正是这样给我的:所有有效属性的列表。但是标准的.Net反射方法在应用于XmlProvider提供的类型时似乎并没有达到我所期望的效果。

因此,既然反射似乎没有达到我的预期,那么我应该做什么来获得XmlProvider为我的类型创建的有效属性列表?

XML类型提供程序是一个擦除类型提供程序,所有表示XML元素的对象在编译的代码中都成为同一类型的FSharp.Data.Runtime.BaseTypes.XmlElement值。提供的属性将被擦除,并替换为通过名称查找访问属性值的一段代码。

这意味着反射将永远无法看到所提供的属性。获取这些信息的唯一方法是访问底层XElement并直接使用它。例如,要获得子元素,可以编写:

[ for e in firstObject.XElement.Elements() -> e.Name.LocalName ]

对于示例中的第一个元素,这将返回一个带有["color"; "shape"; "children"]的列表。

最新更新