按顺序保留顺序(LINQ To XSD)

时间:2009-10-28 15:50:20

标签: c# linq xsd xsd.exe linq-to-xsd

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

2 个答案:

答案 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,但我没有测试过。