c# - 如何将元素添加到 c# XSD 生成的序列化类中的数组?

标签 c# xml xsd xml-serialization

我被一个需要在 InfoPath 中创建一个应用程序的项目所困扰,该应用程序采用了巨大的表单。为了从 InfoPath XML 访问数据,我选择使用 XSD 实用程序创建一个基于 InfoPath 生成的 XML 架构的序列化 c# 类。

由于 InfoPath 表单包含多个表,因此这些表在序列化类中实现为行类型的数组。当 XML 被读入(反序列化)时,显然正在分配和填充数组元素。

我想不通的是如何添加额外的数组元素。例如,如果 XML 在表中有两个条目,则数组将分配两个元素。但我希望能够向数组中添加其他元素。

我尝试使用 Array.Resize 方法,但运气不佳。

这听起来很熟悉吧?

-汤姆

最佳答案

我会利用扩展方法(或分部类)来轻松地向 XSD.exe 创建的类中的数组添加项目。由于 XSD.exe 生成数组而不是列表,因此向数组添加元素有点麻烦。如果您使用扩展方法,则可以使这些类更易于使用。

下面的示例代码基于我使用以下 xml 创建的一组类:

<?xml version="1.0" encoding="utf-8" ?>
<Doc>
  <Item Text="A" />
  <Item Text="B" />
  <Item Text="C" />
  <Item Text="D" />
</Doc>

以下程序将上述 XML 反序列化为 Doc 对象,并利用 AddDocItem 扩展方法将项目添加到 Doc.Items数组。 AddDocItem 使用 Array.Resize 添加元素。

using System;
using System.IO;
using System.Xml.Serialization;

namespace TestConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var xmlSerialzer = new XmlSerializer(typeof(Doc));
            var doc = xmlSerialzer.Deserialize(
                new StreamReader(@"..\..\XmlFile1.xml")) as Doc;
            if(doc == null) return;
            doc.PrintDocItems();
            Console.WriteLine();

            //Add a couple new items
            doc.AddDocItem(new DocItem { Text = "E" });
            doc.AddDocItem(new DocItem { Text = "F" });
            doc.PrintDocItems();
        }
    }

    public static class DocExtensions
    {
        public static void AddDocItem(this Doc doc, DocItem item)
        {
            var items = doc.Items;
            Array.Resize(ref items, items.Length + 1);
            items[items.Length - 1] = item;
            doc.Items = items;
        }

        public static void PrintDocItems(this Doc doc)
        {
            foreach (var item in doc.Items)
                Console.WriteLine(item.Text);
        }
    }
}

如果您不喜欢扩展方法,您可以利用 XSD.exe 生成的类是部分类这一事实,并以这种方式扩展类。例如:

public partial class Doc
{
    public void AddDocItem(DocItem item)
    {
        var items = Items;
        Array.Resize(ref items, items.Length + 1);
        items[items.Length - 1] = item;
        Items = items;
    } 

    public void PrintDocItems()
    {
        foreach (var item in Items)
            Console.WriteLine(item.Text);
    }
}

任何一种方式都应该可以正常工作。

XSD.exe生成的代码如下所示,供引用:

namespace TestConsoleApplication1
{
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
    public partial class Doc {

        private DocItem[] itemsField;

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("Item", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public DocItem[] Items {
            get {
                return this.itemsField;
            }
            set {
                this.itemsField = value;
            }
        }
    }

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
    public partial class DocItem {

        private string textField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Text {
            get {
                return this.textField;
            }
            set {
                this.textField = value;
            }
        }
    }
}

希望对您有所帮助。

关于c# - 如何将元素添加到 c# XSD 生成的序列化类中的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7035455/

相关文章:

java - Alfresco java webscript 的 ServiceRegistry 为空

python lxml : import XSD from a buffer?

c# - SELECT Entity Framework 中的异常处理

c# - 如何为 dotnet 工具安装修复 NU1212

java - hibernate -OGM [PersistenceUnit : person] Unable to build Hibernate SessionFactory

XML Schema - 如何有条件地要求地址元素? (街道、城市、州等)

java - XSD:将元素的属性值限制为父属性的子字符串

c# - 如何在 .NET Winforms 的按钮组中一次选择一个按钮

c# - AutoMapper 覆盖递归类型

xml - RESTful 网络服务 : trying to achieve HATEOAS with custom XML