使用 DataContractSerializer 的接口中的显式类型
Posted
技术标签:
【中文标题】使用 DataContractSerializer 的接口中的显式类型【英文标题】:Explicit types from interfaces using DataContractSerializer 【发布时间】:2021-07-10 11:46:09 【问题描述】:我正在使用 WPF 中的 DataContractSerializer 编写 XML。我需要 XML 尽可能干净(不需要反序列化回同一个应用程序),没有任何命名空间等。 这主要是可行的,但是当我的 Arrays/Lists/IEnumerables 是接口类型时,我遇到了问题。
作为最小的工作示例,我想序列化以下数据结构:
namespace HR
public interface IEmployee
string FirstName get;
string LastName get;
[DataContract(Namespace = "")]
[KnownType(typeof(Employee))]
public class Employee : IEmployee
public Employee(string firstName, string lastName)
FirstName = firstName;
LastName = lastName;
[DataMember]
public string FirstName get; set;
[DataMember]
public string LastName get; set;
namespace Business
[DataContract(Namespace ="")]
public class Company
[DataMember]
public string CompanyName get; set;
[DataMember]
public IEmployee CEO get; set;
[DataMember]
public IEnumerable<IEmployee> Employees;
我序列化的方式如下:
namespace Program
static void Main(string[] args)
Employee jimApple = new Employee("Jim", "Apple");
Employee bob = new Employee("Bob", "the Builder");
Company company = new Company
CEO = jimApple,
Employees = new List<Employee> jimApple, bob
;
var outputPath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "Test.xml");
Stream outputStream = new System.IO.FileStream(outputPath, FileMode.Create);
using (var writer = XmlWriter.Create(outputStream, new XmlWriterSettings Indent = true ))
var serializer = new DataContractSerializer(typeof(Company));
serializer.WriteObject(writer, company);
写出来的内容如下:
<?xml version="1.0" encoding="utf-8"?>
<Company xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CEO xmlns="" i:type="Employee">
<FirstName>Jim</FirstName>
<LastName>Apple</LastName>
</CEO>
<CompanyName i:nil="true" />
<Employees xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:anyType xmlns="" i:type="Employee">
<FirstName>Jim</FirstName>
<LastName>Apple</LastName>
</d2p1:anyType>
<d2p1:anyType xmlns="" i:type="Employee">
<FirstName>Bob</FirstName>
<LastName>the Builder</LastName>
</d2p1:anyType>
</Employees>
</Company>
现在这已经差不多好了,但我需要 <d2p1:anyType xmlns="" i:type="Employee">
行看起来像 <Employee>
。另外我更喜欢去掉xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
。
我一直在研究 DataContractResolver 类来做这种事情,但没有运气。有什么方法可以实现上述目标?
【问题讨论】:
【参考方案1】:您应该考虑使用自定义集合类型并使用CollectionDataContract
属性对其进行装饰:
[DataContract(Namespace = "")]
public class Company
[DataMember]
public string CompanyName get; set;
[DataMember]
public IEmployee CEO get; set;
[DataMember]
public EmployeeCollecion Employees;
[CollectionDataContract(ItemName = "Employee", Namespace = "")]
public class EmployeeCollecion : List<Employee>
public EmployeeCollecion() : base()
public EmployeeCollecion(int capacity) : base(capacity)
public EmployeeCollecion(IEnumerable<Employee> collection) : base(collection)
这可能是您使用DataContractResolver
所能达到的程度。如果您需要自定义序列化并且“不需要反序列化回同一个应用程序”,那么自己进行序列化似乎更容易。
【讨论】:
它确实有效,但我有点难过它需要更改数据结构来实现它 @Yellow:嗯,就像我说的,如果你想要最大的灵活性,你最好编写自己的自定义序列化程序。以上是关于使用 DataContractSerializer 的接口中的显式类型的主要内容,如果未能解决你的问题,请参考以下文章
使用 DataContractSerializer 时设置属性的初始值
使用 DataContractSerializer 和 XmlDictionaryWriter 序列化 JObject 后崩溃
在原语列表上使用 DataContractSerializer 的自定义元素名称
使用 DataContractSerializer 的接口中的显式类型