Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.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#中使用自定义序列化时,如何控制XML元素的名称?_C#_Xml_.net Core_Serialization - Fatal编程技术网

在C#中使用自定义序列化时,如何控制XML元素的名称?

在C#中使用自定义序列化时,如何控制XML元素的名称?,c#,xml,.net-core,serialization,C#,Xml,.net Core,Serialization,我正在使用一个需要符合的外部开发的XSD,其中一个字段引擎可以是两种类型之一:电动或燃烧。两者都是从超级类引擎派生的 有多种方法可以让C#中的XmlSerializer处理这个问题,但所有方法似乎都有相同的副作用:当使用自定义序列化程序时,默认的序列化命名约定都会被抛出窗口。我想模拟类车辆的其余字段的默认行为 考虑以下几点: 使用系统; 使用System.Xml; 使用System.Xml.Schema; 使用System.Xml.Serialization; 名称空间DMV { 公共类车辆:I

我正在使用一个需要符合的外部开发的XSD,其中一个字段
引擎
可以是两种类型之一:
电动
燃烧
。两者都是从超级类
引擎
派生的

有多种方法可以让C#中的
XmlSerializer
处理这个问题,但所有方法似乎都有相同的副作用:当使用自定义序列化程序时,默认的序列化命名约定都会被抛出窗口。我想模拟类
车辆
的其余字段的默认行为

考虑以下几点:

使用系统;
使用System.Xml;
使用System.Xml.Schema;
使用System.Xml.Serialization;
名称空间DMV
{
公共类车辆:IXmlSerializable
{
公共引擎引擎{get;set;}
[XmlElement(“制造商”)]
上市公司制造商{get;set;}
public void WriteXml(XmlWriter)
{
XmlSerializer engineSerializer=新的XmlSerializer(Engine.GetType());
engineSerializer.Serialize(编写器、引擎);
XmlSerializer manufacturerSerializer=新的XmlSerializer(Manufacturer.GetType());
制造商系列化(作者、制造商);
}
}
公共抽象类引擎{}
公共级电动发动机
{
公共整数极点{get;set;}
}
公共级燃烧发动机
{
公共int CC{get;set;}
}
公营公司
{
公共字符串名称{get;set;}
}
}
我尝试使用以下序列化代码运行此操作:

车辆=新车();
车辆。发动机=新电动();
车辆制造商=新公司();
XmlSerializer serializer=新的XmlSerializer(类型(车辆));
TextWriter writer=新的StringWriter();
序列化器。序列化(编写器、车辆);
Console.WriteLine(writer.ToString());
writer.Close();
结果是产生了以下一堆粪便:


0
(是的,
引擎
字段已正确序列化,但
公司
没有这么多。)

如果我使用默认(内置)序列化,我会得到以下(期望的!)输出:


如何既序列化派生类
Electric
Combustion
,又保留field
Manufacturer
(类型
Company
)的默认命名约定?

尝试使用接受“其他类型”数组的for
XmlSerializer
来处理派生类,而不是实现
IXmlSerializable
并手动执行序列化。序列化程序现在将处理您的派生类,但也会按照您想要的方式提取其他属性(例如
xmlement
):

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

namespace SomeNamespace
{
    public class Program
    {
        static void Main()
        {
            Vehicle vehicle = new Vehicle();
            vehicle.Engine = new Electric();
            vehicle.Manufacturer = new Company();

            XmlSerializer serializer = new XmlSerializer(typeof(Vehicle), new Type[] { typeof(Combustion), typeof(Electric)});
            TextWriter writer = new StringWriter();
            serializer.Serialize(writer, vehicle);

            Console.WriteLine(writer.ToString());
            writer.Close();
        }
    }

    public class Vehicle
    {
        public Engine Engine { get; set; }
        [XmlElement("Manufacturer")]
        public Company Manufacturer { get; set; }
    }

    public abstract class Engine { }

    public class Electric : Engine
    {
        public int Poles { get; set; }
    }

    public class Combustion : Engine
    {
        public int CC { get; set; }
    }

    public class Company
    {
        public string Name { get; set; }
    }

}
产出:

<?xml version="1.0" encoding="utf-16"?>
<Vehicle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Engine xsi:type="Electric">
    <Poles>0</Poles>
  </Engine>
  <Manufacturer />
</Vehicle>

0

与公认的答案不同,这种方法的优点是不将基类链接到所有可能的派生类。(在这种方法中,每次添加新的派生类型时,都必须返回并编辑基类型。)虽然此示例对派生类型数组进行了
Program.Main()
硬编码,但您也可以轻松地使用反射来构建该数组,从而使添加新的派生类型更加容易。

有两种方法

  • XmlRoot
    属性添加到
    Company
    类定义:

     [XmlRoot("Manufacturer")]
     public class Company
    
  • XmlRootAttribute
    添加到
    XmlSerializer
    构造函数

     manufacturerSerializer = new XmlSerializer(Manufacturer.GetType(),
         new XmlRootAttribute("Manufacturer"));
    
    请注意这一点:


  • 通过执行以下操作,可以摆脱自定义序列化程序:

    public class Vehicle
    {
        [XmlElement(typeof(Electric), ElementName = "Electric")]
        [XmlElement(typeof(Combustion), ElementName = "Combustion")]
        public Engine Engine { get; set; }
        [XmlElement("Manufacturer")]
        public Company Manufacturer { get; set; }
    }
    

    谢谢你的意见。我应该在我的描述中添加
    Company
    正在XML中的其他上下文中使用,例如
    RentalCompany
    ,因此不能在类级别绑定到特定的名称。