保留选择序列的顺序 (LINQ To XSD)

发布于 2024-08-09 09:04:31 字数 514 浏览 1 评论 0 原文

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

Given the following XML example we could imagine a schema defining Root as containing a sequence of unbound number of choices between Type1 and Type2.

<Root>
    <Type1 />
    <Type2 />
    <Type2 />
    <Type1 />
</Root>

I am testing out migrating from the XSD.exe tool which although adds type-safety has a lot of little annoyances. The XSD tool in this case just creates within Root an array of type System.Object and you have to figure out what type of objects (Type1 or Type2) are in there. Its not completely elegant, but at least you preserve order.

The problem is when LINQ to XSD creates the objects, it defines Root as having two independent lists of Type1 and Type2. This is great in that it is type-safe, but I now appear to lose the order of the elements. I built LINQ to XSD from the source on codeplex.

Using LINQ to XSD, how can I preserve the order of these elements?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

山色无中 2024-08-16 09:04:31

如何围绕 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 中创建方法来包装查询。

How about creating a wrapper around Choice? Limiting the types that it accesses like this:

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; }
    }
}

This is a simplified version, and you will have to add more validation (if _value is of correct type, what is the current type of _value, etc).

Then, you can filter it with LINQ:

var q1 = from v in root.Sequence
         where v.CurrentType == ChoiceEnum.Type1
         select v.Type1;

Or you can create methods in Root that will wrap the queries.

微暖i 2024-08-16 09:04:31

Linq2Xsd 仅当存在 xsd:choice 元素时才会在序列上出错。

幸运的是,我能够删除 Amazon XSD(我只是没有使用 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> 

然后,生成的代码在构造函数中正确地包含此内容,该构造函数保留了顺序。

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 一起使用。这是此处描述的,但我还没有测试过。

Linq2Xsd only trips up on sequences when there's an xsd:choice element.

Fortunately I was able to remove the xsd:choice for the Amazon XSD I am using (I just wasn't using MerchantOrderID), which allowed the sequence to properly be preserved in the ToString() for the 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> 

The generated code then correctly has this in the constructor which preserves the order

contentModel = new SequenceContentModelEntity(
               new NamedContentModelEntity(XName.Get("AmazonOrderID", "")), 
               new NamedContentModelEntity(XName.Get("ActionType", "")), 
               new NamedContentModelEntity(XName.Get("CODCollectionMethod", "")), 
               new NamedContentModelEntity(XName.Get("AdjustedItem", "")));

You may also be able to do this manually by subclassing it youself, but I'm not sure how this would work with an xsd:choice. This is described here but I haven't tested it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文