我尝试使用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>
(在真实数据文件中,&#34; Guid001&#34;等等是真正的GUID;但对于这个虚构的例子,我保持简单。)
基本上,它是一个包含大量object
元素的平面数据文件,每个元素都来自此数据来自的程序中的C#类实例。元素半随机混合在一起,在同一数据文件中表示几个不同的类族。 (这就是为什么我的虚构数据文件将绘图形状与人物记录混合在一起 - 我正在使用的真实数据文件在单个文件中具有类似的关注点。)
正如我所说,我已经为我的代表性样本或多或少随机选择了一堆记录。我试图从每个班级中挑选至少一个,这样我就可以覆盖大部分属性名称,但是如果(例如)我最终选择了Guid004用于Quux类而不是Guid003?然后我提供的类型实际上不知道SecondaryColor
属性。我想我可以在我提供的类型上使用.GetType()
,然后调用.GetProperties()
以获取我提供的认为所知道的所有属性的列表。但是当我这样做时:
let firstObject = rootElement.Objects[0]
printfn "%A" firstObject.GetType().GetProperties()
而不是像我期待的那样获得名为Color
,Shape
,Children
,FirstName
等的属性列表,而是获得的正是两个属性,XElement
和_Print
。
我想,我可以在我的实际数据中迭代所有XElement
并将一组子元素名称组合在一起。然后从我的样本数据中获取子元素名称集,并比较这两组。如果两组相等(例如,它们之间的差异是空集),那么我知道我已经覆盖了样本数据中的所有基础。
但是,我正在使用XmlProvider,因为我不想要处理XElement
及其怪癖(如XName
s everywhere instead of strings和等等)。我知道可能来检索XmlProvider提供的类型的有效属性列表,因为Atom中的自动完成下拉列表(通过Ionide)正好给出了我:所有的列表有效的财产。但是,当应用于XmlProvider提供的类型时,标准.Net反射方法似乎没有做我期望的事情。
因为反射似乎没有按照我的预期进行, 我应该做什么来获取XmlProvider为我的类型创建的有效属性列表?
答案 0 :(得分:6)
XML类型提供程序是一种擦除类型提供程序,表示XML元素的所有对象在编译代码中变为名为FSharp.Data.Runtime.BaseTypes.XmlElement
的相同类型的值。提供的属性将被删除,并替换为一段通过名称查找访问属性值的代码。
这意味着反射将永远无法看到提供的属性。获得这些的唯一方法是访问基础XElement
并直接使用它。例如,要获取子元素,您可以编写:
[ for e in firstObject.XElement.Elements() -> e.Name.LocalName ]
在示例的第一个元素上,返回一个包含["color"; "shape"; "children"]
的列表。