C# 当自定义对象列表是泛型类型时,如何使用特定架构中另一个自定义对象的列表序列化自定义对象

C# 当自定义对象列表是泛型类型时,如何使用特定架构中另一个自定义对象的列表序列化自定义对象,c#,.net,xml,generics,serialization,C#,.net,Xml,Generics,Serialization,我需要创建很多XML文件。它们非常相似,需要具有以下模式: <Servidor> <VersaoLayout>0001</VersaoLayout> <!--Will not change--> <CodigoUJ>001001</CodigoUJ> <!--Will not change--> <ItemServidor> <!--

我需要创建很多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>
<Servidor>
  <VersaoLayout>versao01</VersaoLayout>
  <CodigoUJ>999</CodigoUJ>
  <ItensLayout>
    <ServidorLayout>
      <CPFServidor>4252813450</CPFServidor>
      <NomeServidor>Antonio de Sousa Muniz</NomeServidor>
    </ServidorLayout>
  </ItensLayout>
</Serv>

0001
001001
13579024681
富拉诺佩雷拉酒店
请注意,对于我需要创建的所有文件,
标记都是相同的,
是不同的内容。所以我想:为什么不创建一个类并使用泛型来处理这种情况下的差异呢?目前我的课程如下:

//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; }
}
 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;
  }
//一种容器类,它将保存不同的内容。
[XmlRoot(“服务商”,ElementName=“服务商”)]
公共类LayoutArquivoXML,其中T:ItemLayout
{
[XmlElement(“VersaoLayout”)]
公共字符串VersaoLayout{get;set;}
[XmlElement(“CodigoUJ”)]
公共字符串CodigoUJ{get;set;}
//[XmlArrayItem(“ItemServidor”)]
公共列表ItensLayout{get;set;}
//为简单起见省略了构造函数
}
//“内容类”。我将有一系列类似的课程
[XmlRoot(“ItemServidor”,ElementName=“ItemServidor”)]
公共类服务布局:ItemLayout
{
[XmlElement(“CPFServidor”)]
公共字符串CPFServidor{get;set;}
[XmlElement(“NomeServidor”)]
公共字符串Nome{get;set;}
}
我以这种方式实例化我的“容器类”:

LayoutArquivoXML<ServidorLayout> layout = new Layout.LayoutArquivoXML<ServidorLayout>("versao01", "999", lstItensLayout.ToList());
LayoutArquivoXML布局=新布局.LayoutArquivoXML(“versao01”,“999”,lstItensLayout.ToList());
我的序列化方法如下所示:

//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; }
}
 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;
  }
公共字符串序列化程序(T对象)
{
stringxml=string.Empty;
使用(var sw=new ISO8859StringWriter())
{
XmlSerializerNamespaces ns=新的XmlSerializerNamespaces();
ns.Add(“,”);//省略XML名称空间
var xs=新的XmlSerializer(typeof(T));
序列化(sw、objeto、ns);
}
返回xml;
}
这些图形对象正在生成具有以下架构的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>
<Servidor>
  <VersaoLayout>versao01</VersaoLayout>
  <CodigoUJ>999</CodigoUJ>
  <ItensLayout>
    <ServidorLayout>
      <CPFServidor>4252813450</CPFServidor>
      <NomeServidor>Antonio de Sousa Muniz</NomeServidor>
    </ServidorLayout>
  </ItensLayout>
</Serv>

versao01
999
4252813450
安东尼奥·德索萨·穆尼兹
我不希望标记
在XML中。我需要做什么才能在所需的模式中生成XML

此外,根标记
需要根据我生成的文件进行更改,假设我需要创建另一个文件,其中根标记是另一个,假设:

LayoutArquivoXML<AnotherLayout> layout = new Layout.LayoutArquivoXML<AnotherLayout>("versao01", "999", anotherItensLayout.ToList());
LayoutArquivoXML布局=新布局.LayoutArquivoXML(“versao01”,“999”,anotherItensLayout.ToList());

有两个不同的问题

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

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

此外,根标记
需要根据我生成的文件进行更改

这由
XmlRoot
属性控制

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

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

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 objeto,XmlAttributeOverrides overrides overrides=null)
{
stringxml=string.Empty;
使用(var sw=new ISO8859StringWriter())
{
XmlSerializerNamespaces ns=新的XmlSerializerNamespaces();
ns.Add(“,”);//省略XML名称空间
var xs=新的XmlSerializer(typeof(T),重写);
序列化(sw、objeto、ns);
xml=sw.ToString();
}
返回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");
publicstringserializador(LayoutArquivoXML对象、stringrootelementname、stringcontentelementname)
其中T:ItemLayout
{
var xmlAttrOverrides=新的XmlAttributeOverrides();
//根元素名称重写
var xmlRootAttrs=新的XmlAttributes();
xmlRootAttrs.XmlRoot=新的XmlRootAttribute(rootElementName);
Add(typeof(LayoutArquivoXML),xmlRootAttrs);
//内容元素名称覆盖
var xmlContentAttrs=新的XmlAttributes();
添加(新的XmlElementAttribute(contentElementName));
Add(typeof(LayoutArquivoXML),“ItensLayout”,xmlContentAttrs);
//调用传递重写的原始方法
返回Serializador(objeto、xmlAttrOverrides);
}
现在,您可以通过以下方式实现您的目标:

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");
var source=new LayoutArquivoXML
{
VersaoLayout=“0001”,
CodigoUJ=“001001”,
ItensLayout=新列表
{
新服务设施布局
{
CPFServidor=“13579024681”,
Nome=“Fulano Pereira Tal”,
},
}
};
var xml=Serializador(来源,“Servidor”、“ItemServidor”);
产生:

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

0001
001001
13579024681
富拉诺佩雷拉酒店

您提出的是独立的问题。您的第一个问题,即如何使元素名称与泛型参数类型名称匹配,非常类似于。对于第二个问题,关于如何修改泛型的根名称,您将需要子类化
LayoutArquivoXML。谢谢,它太完美了!