当此自定义对象列表是泛型类型时,如何使用特定模式中的另一个自定义对象的列表序列化自定义对象

时间:2017-04-26 21:25:04

标签: c# .net xml generics serialization

我需要创建大量的XML文件。它们非常相似,需要具有以下模式:

<Servidor>
  <VersaoLayout>0001</VersaoLayout> <!--Will not change-->
  <CodigoUJ>001001</CodigoUJ>       <!--Will not change-->
    <ItemServidor>                  <!--A list of <T> that will change-->
      <CPFServidor>13579024681</CPFServidor>
      <NomeServidor>Fulano Pereira Tal</NomeServidor>
    </ItemServidor>
</Servidor>

请注意,标记<VersaoLayout><CodigoUJ>对于我需要创建的所有文件都是相同的,<ItemServidor>是不同的内容。所以我想:为什么不创建一个类并使用泛型来处理这种情况的差异?目前我的课程如下:

//Kind of a container class that will hold the content that will vary.
[XmlRoot("Servidor", ElementName="Servidor")]
public class LayoutArquivoXML<T> where T : ItemLayout
{
    [XmlElement("VersaoLayout")]
    public string VersaoLayout { get; set; }

    [XmlElement("CodigoUJ")]
    public string CodigoUJ { get; set; }

    //[XmlArrayItem("ItemServidor")]
    public List<T> ItensLayout { get; set; }

    // Constructors omited for simplicity
}

//A "ContentClass". I will have a bunch of classes similar to this
[XmlRoot("ItemServidor", ElementName = "ItemServidor")]
public class ServidorLayout : ItemLayout  
{
    [XmlElement("CPFServidor")]
    public string CPFServidor { get; set; }

    [XmlElement("NomeServidor")]
    public string Nome { get; set; }
}

我正在实例化我的&#34;容器类&#34;这样:

LayoutArquivoXML<ServidorLayout> layout = new Layout.LayoutArquivoXML<ServidorLayout>("versao01", "999", lstItensLayout.ToList());

我的序列化方法如下:

 public string Serializador<T>(T objeto)
 {
     string xml = string.Empty;
     using (var sw = new ISO8859StringWriter())
     {
         XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
         ns.Add("", ""); // to omit XML namespaces
         var xs = new XmlSerializer(typeof(T));
         xs.Serialize(sw, objeto, ns);
      }
      return xml;
  }

这些对象图正在生成具有以下模式的XML:

<Servidor>
  <VersaoLayout>versao01</VersaoLayout>
  <CodigoUJ>999</CodigoUJ>
  <ItensLayout>
    <ServidorLayout>
      <CPFServidor>4252813450</CPFServidor>
      <NomeServidor>Antonio de Sousa Muniz</NomeServidor>
    </ServidorLayout>
  </ItensLayout>
</Serv>

我不想在XML中使用标记<ItensLayout>标记。我需要做什么才能在所需的模式中生成XML?

此外,根标记<Servidor>将需要根据我生成的文件进行更改,想象我需要创建另一个文件,其中根标记为另一个,让我们说:

LayoutArquivoXML<AnotherLayout> layout = new Layout.LayoutArquivoXML<AnotherLayout>("versao01", "999", anotherItensLayout.ToList());

1 个答案:

答案 0 :(得分:1)

有两个不同的问题。

  

我不希望XML中的标记<ItensLayout>标记。我需要做什么才能在所需的模式中生成XML?

documentation中针对将数组序列化为元素序列所述,要将数组(列表,可枚举等)序列化为XML元素的平面序列,您需要将XmlElement属性应用于属性/字段。

  

此外,根标记<Servidor>将需要根据我正在生成的文件进行更改

这由XmlRoot属性控制。

现在,如果您使用的是具体类,则所有这些都适用。要将它们动态应用于您的通用类,您可以使用XmlOverrides类和XmlSerializer constructors接受此类参数。

为此,首先在原始方法中添加一个可选参数:

public string Serializador<T>(T objeto, XmlAttributeOverrides overrides = null)
{
    string xml = string.Empty;
    using (var sw = new ISO8859StringWriter())
    {
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", ""); // to omit XML namespaces
        var xs = new XmlSerializer(typeof(T), overrides);
        xs.Serialize(sw, objeto, ns);
        xml = sw.ToString();
    }
    return xml;
}

然后创建一个这样的特定方法:

public string Serializador<T>(LayoutArquivoXML<T> objeto, string rootElementName, string contentElementName)
     where T : ItemLayout
{
    var xmlAttrOverrides = new XmlAttributeOverrides();
    // Root element name override
    var xmlRootAttrs = new XmlAttributes();
    xmlRootAttrs.XmlRoot = new XmlRootAttribute(rootElementName);
    xmlAttrOverrides.Add(typeof(LayoutArquivoXML<T>), xmlRootAttrs);
    // Content element name override
    var xmlContentAttrs = new XmlAttributes();
    xmlContentAttrs.XmlElements.Add(new XmlElementAttribute(contentElementName));
    xmlAttrOverrides.Add(typeof(LayoutArquivoXML<T>), "ItensLayout", xmlContentAttrs);
    // Call the original method passing the overrides
    return Serializador(objeto, xmlAttrOverrides);
}

现在,您可以通过使用以下内容实现目标:

var source = new LayoutArquivoXML<ServidorLayout>
{
    VersaoLayout = "0001",
    CodigoUJ = "001001",
    ItensLayout = new List<ServidorLayout>
    {
        new ServidorLayout
        {
            CPFServidor = "13579024681",
            Nome = "Fulano Pereira Tal",
        },
    }
};

var xml = Serializador(source, "Servidor", "ItemServidor");

产生:

<Servidor>
  <VersaoLayout>0001</VersaoLayout>
  <CodigoUJ>001001</CodigoUJ>
  <ItemServidor>
    <CPFServidor>13579024681</CPFServidor>
    <NomeServidor>Fulano Pereira Tal</NomeServidor>
  </ItemServidor>
</Servidor>