鉴于以下XML示例,我们可以想象一个定义Root的模式,其中包含Type1和Type2之间未绑定数量的选择序列。
<Root>
<Type1 />
<Type2 />
<Type2 />
<Type1 />
</Root>
我正在测试从XSD.exe工具迁移,虽然添加类型安全性有很多小烦恼。在这种情况下,XSD工具只是在Root中创建一个System.Object类型的数组,你必须弄清楚那里有什么类型的对象(Type1或Type2)。它并不完全优雅,但至少你保留了秩序。
问题是当LINQ to XSD创建对象时,它将Root定义为具有两个独立的Type1和Type2列表。这很棒,因为它是类型安全的,但我现在似乎失去了元素的顺序。我在codeplex上从源代码构建了LINQ to XSD。
使用LINQ to XSD,我如何保留这些元素的顺序?
答案 0 :(得分:2)
如何围绕Choice创建包装器?限制它访问的类型如下:
class Choice
{
private object _value;
public ChoiceEnum CurrentType { get; private set; }
public Type1 Type1Value
{
get { return (Type1) _value; }
set { _value = value; CurrentType = ChoiceEnum.Type1; }
}
public Type2 Type2Value
{
get { return (Type2) _value; }
set { _value = value; CurrentType = ChoiceEnum.Type2; }
}
}
这是一个简化版本,您必须添加更多验证(如果_value
的类型正确,_value
的当前类型是什么,等等。)
然后,您可以使用LINQ过滤它:
var q1 = from v in root.Sequence
where v.CurrentType == ChoiceEnum.Type1
select v.Type1;
或者您可以在Root中创建将包装查询的方法。
答案 1 :(得分:1)
当有xsd:choice元素时,Linq2Xsd只会跳过序列。
幸运的是,我能够删除我正在使用的Amazon XSD的xsd:choice(我只是没有使用MerchantOrderID),这允许在ToString()
中正确保留序列XML。
<xsd:choice> <--- removed line
<xsd:element ref="AmazonOrderID"/>
<xsd:element ref="MerchantOrderID"/> <--- removed line
</xsd:choice> <--- removed line
<xsd:element name="ActionType" minOccurs="0" maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Refund"/>
<xsd:enumeration value="Cancel"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
然后,生成的代码在保留订单
的构造函数中正确地生成了此代码contentModel = new SequenceContentModelEntity(
new NamedContentModelEntity(XName.Get("AmazonOrderID", "")),
new NamedContentModelEntity(XName.Get("ActionType", "")),
new NamedContentModelEntity(XName.Get("CODCollectionMethod", "")),
new NamedContentModelEntity(XName.Get("AdjustedItem", "")));
您也可以通过自己进行子类化来手动执行此操作,但我不确定这对xsd:choice有何用处。这是described here,但我没有测试过。