在C#中使用自定义序列化时,如何控制XML元素的名称?
我正在使用一个需要符合的外部开发的XSD,其中一个字段在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
引擎
可以是两种类型之一:电动
或燃烧
。两者都是从超级类引擎
派生的
有多种方法可以让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
,又保留fieldManufacturer
(类型Company
)的默认命名约定?尝试使用接受“其他类型”数组的forXmlSerializer
来处理派生类,而不是实现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
,因此不能在类级别绑定到特定的名称。