C# 如何用派生类序列化基类
你好, 我有以下示例代码:C# 如何用派生类序列化基类,c#,serialization,C#,Serialization,你好, 我有以下示例代码: public class Vehicule { public string Name { get; set; } public Brand Brand { get; set; } } public class Car : Vehicule { public string Matriculation { get; set; } } public class Brand { public string Name { get; set;
public class Vehicule
{
public string Name { get; set; }
public Brand Brand { get; set; }
}
public class Car : Vehicule
{
public string Matriculation { get; set; }
}
public class Brand
{
public string Name { get; set; }
}
public class Renault : Brand
{
public string Information { get; set; }
}
如果创建此实例:
var car = new Car { Name = "Clio", Matriculation = "XXX-XXX", Brand = new Renault { Name = "Renault", Information = "Contact Infos" } };
当我像那样序列化此对象时:
var serializer = new XmlSerializer(typeof(Car), new Type[] { typeof(Renault)});
serializer.Serialize(wr, car);
我得到这个:
<?xml version="1.0" encoding="utf-8"?>
<Car xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Clio</Name>
<Brand xsi:type="Renault">
<Name>Renault</Name>
<Information>Contact Infos</Information>
</Brand>
<Matriculation>XXX-XXX</Matriculation>
</Car>
Xml:
<?xml version="1.0" encoding="utf-8"?>
<Vehicule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Clio</Name>
<Brand>
<Name>Renault</Name>
</Brand>
</Vehicule>
克利奥
雷诺
您能帮我获取好的Xml(仅适用于基本类型车辆和品牌)吗
非常感谢您不能神奇地将派生类序列化为其基础,因为 “…序列化通过调用Object.getType()检查实例的类型 方法。此方法始终返回对象的确切类型。“ 如果您确实只需要序列化基类,那么这里的解决方案是实现IXmlSerializable接口并创建您自己的自定义序列化程序 IXmlSerializable: 再想一想。如果您可以绕过输出额外XML元素的限制,那么您就可以仅使用基类对象序列化派生类,方法是1)使用基类上的来告诉它需要哪些类型,或者2)使用获取类型列表的重载 编辑: 再仔细考虑一下,一种解决方法是在基对象上添加Clone()方法,然后序列化基对象的克隆 LinqPad代码:
public class Vehicule
{
public string Name { get; set; }
public Brand Brand { get; set; }
public Vehicule Clone()
{
return new Vehicule { Name = this.Name, Brand = new Brand { Name = this.Brand.Name } };
}
}
public class Car : Vehicule
{
public string Matriculation { get; set; }
}
public class Brand
{
public string Name { get; set; }
}
public class Renault : Brand
{
public string Information { get; set; }
}
void Main()
{
var car = new Car { Name = "Clio", Matriculation = "XXX-XXX", Brand = new Renault { Name = "Renault", Information = "Contact Infos" } };
var vehicle = car as Vehicule;
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(Vehicule));
XmlWriterSettings settings = new XmlWriterSettings
{
Encoding = new UnicodeEncoding(false, false),
Indent = false,
OmitXmlDeclaration = false
};
using(StringWriter textWriter = new StringWriter())
using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) {
serializer.Serialize(xmlWriter, vehicle.Clone());
textWriter.ToString().Dump();
}
}
这是继承的问题之一,也是支持组合的另一个原因 我在一个移动应用程序上遇到了同样的问题,我有一个
Contact
类,它源自ContactSummary
。存储库返回Contact
实例,但在很多情况下,我只希望ContactSummary
能够节省消息大小和数据使用量等。默认的Xml和Json序列化器只有在派生类具有基类的[KnownType()]
属性时才能工作,但这仍然意味着所有这些额外的财产都要通过电线
使用继承实现可行的解决方案是有问题的,我不想求助于自定义序列化程序,如果解决方案是用复制构造函数和克隆属性污染DTO,那么为什么不将DTO改为使用组合呢
如果您可以控制DTO,那么将其重组为使用组合而不是继承可能是答案。在我的例子中,它相当简单
public class ContactSummary
{
public string Name { get; set;}
public string Phone { get; set; }
}
public class Contact
{
public ContactSummary Summary { get; set; }
// ... other properties here
}
在您的示例中,Car
将需要包含对Vehicle
的引用,而不是从它继承-类似于
[KnowTypes(typeof(Renault))]
public class Vehicle
{
public string Name { get; set; }
public Brand Brand { get; set; }
}
public class Car
{
public Vehicle Vehicle { get; set; }
public string Matriculation { get; set; }
}
然后,当您想要示例中的“base”类型时,只需序列化
Car.Vehicle
就可以了,因为XML序列化程序的工作方式决定了不需要一些手动工作。您可以创建一个基实例并将值映射到上面,或者在此处查看RichardOD的答案:感谢TyCobb提供这些信息
[KnowTypes(typeof(Renault))]
public class Vehicle
{
public string Name { get; set; }
public Brand Brand { get; set; }
}
public class Car
{
public Vehicle Vehicle { get; set; }
public string Matriculation { get; set; }
}