7

给定以下 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,如何保留这些元素的顺序?

4

2 回答 2

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 中创建包装查询的方法。

于 2009-12-24T22:24:29.740 回答
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> 

然后生成的代码在构造函数中正确地具有 this 保留顺序

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 一起使用。这在此处进行了描述,但我尚未对其进行测试。

于 2014-03-12T18:54:52.630 回答