Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在选择序列中保持顺序(LINQ到XSD)_C#_Linq_Xsd_Xsd.exe_Linq To Xsd - Fatal编程技术网

C# 在选择序列中保持顺序(LINQ到XSD)

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类型的数组,您必须弄

在下面的XML示例中,我们可以想象一个模式,它将根定义为包含Type1和Type2之间的一系列未绑定的选择

<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", "")));