C# 在选择序列中保持顺序(LINQ到XSD)
在下面的XML示例中,我们可以想象一个模式,它将根定义为包含Type1和Type2之间的一系列未绑定的选择C# 在选择序列中保持顺序(LINQ到XSD),c#,linq,xsd,xsd.exe,linq-to-xsd,C#,Linq,Xsd,Xsd.exe,Linq To Xsd,在下面的XML示例中,我们可以想象一个模式,它将根定义为包含Type1和Type2之间的一系列未绑定的选择 <Root> <Type1 /> <Type2 /> <Type2 /> <Type1 /> </Root> 我正在测试从XSD.exe工具进行迁移,该工具虽然增加了类型安全性,但有很多小麻烦。在本例中,XSD工具只是在根目录中创建一个System.Object类型的数组,您必须弄
<Root>
<Type1 />
<Type2 />
<Type2 />
<Type1 />
</Root>
我正在测试从XSD.exe工具进行迁移,该工具虽然增加了类型安全性,但有很多小麻烦。在本例中,XSD工具只是在根目录中创建一个System.Object类型的数组,您必须弄清楚其中包含什么类型的对象(Type1或Type2)。它并不完全优雅,但至少你保持了秩序
问题是,当LINQ to XSD创建对象时,它将Root定义为具有两个独立的Type1和Type2列表。这很好,因为它是类型安全的,但我现在似乎失去了元素的顺序。我在codeplex上从源代码构建了LINQ到XSD
使用LINQ to XSD,如何保持这些元素的顺序?围绕选项创建一个包装器怎么样?限制它访问的类型,如下所示:
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; }
}
}
这是一个简化版本,您必须添加更多验证(如果\u value
的类型正确,那么\u value
的当前类型是什么,等等)
然后,您可以使用LINQ对其进行过滤:
var q1 = from v in root.Sequence
where v.CurrentType == ChoiceEnum.Type1
select v.Type1;
或者,您可以在根目录中创建方法来包装查询。Linq2Xsd仅在有xsd:choice元素时才会在序列上触发 幸运的是,我能够删除我正在使用的xsd:choice(我只是没有使用MerchantOrderID),这使得序列能够正确地保存在xml的
ToString()
中
<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>
您也可以通过自己将其子类化来手动执行此操作,但我不确定如何使用xsd:choice。这是,但我还没有测试过。您已经介绍了仅有的两个选项。要么得到一个保持顺序的弱类型集合,要么每种类型得到一个强类型集合。假设您根本没有使用任何XML—如何编写一个纯代码对象,其中包含一个强类型集合和多个类型?我的问题是如何使用Linq到XSD来保持此场景中元素的顺序。我意识到要有一个混合类型的集合,它们必须是System.Object(或者它们的共同父级)。在这个场景中,我愿意放弃强类型对象,使用Linq到XSD来保持顺序。我希望有办法迫使它这么做。在我的用例中,顺序很重要,所以我不能使用Linq到XSD,尽管我真的很想这样做,因为它比XSD有很多优点。如果Type1和Type2都有一个公共基类,那么就可以有一个IList。现在您有了一个单一的强类型列表,并且保留了顺序。在遍历列表时,只需检查当前对象的类型。foreach(元素中的基类型el){if(el是Type1)…else if(el是Type2)}撇开其他注释,看起来您已经回答了自己的问题。要获得订单,必须使用某种类型的基类,无论是对象还是您的创建对象,并在运行时进行类型检查。我建议您添加一个答案,然后接受它。:-)如果我没弄错的话,你会因此得到一个徽章。好建议。这应该是可行的,但确实决定了XSD本身的设计,这是不幸的,有时是不可能的(例如,行业标准模式)。我们团队中使用的很多模式都是由我们创建的,所以我们可以使用这种技术。
contentModel = new SequenceContentModelEntity(
new NamedContentModelEntity(XName.Get("AmazonOrderID", "")),
new NamedContentModelEntity(XName.Get("ActionType", "")),
new NamedContentModelEntity(XName.Get("CODCollectionMethod", "")),
new NamedContentModelEntity(XName.Get("AdjustedItem", "")));