Pal*_*ani 34 .net c# xml xml-serialization
"人"可能会引用另一个人.
public class Person
{
public string Name;
public Person Friend;
}
Person p1 = new Person();
p1.Name = "John";
Person p2 = new Person();
p2.Name = "Mike";
p1.Friend = p2;
Person[] group = new Person[] { p1, p2 };
XmlSerializer ser = new XmlSerializer(typeof(Person[]));
using (TextWriter tw = new StreamWriter("test.xml"))
ser.Serialize(tw,group );
//above code generates following xml
<ArrayOfPerson>
<Person>
<Name>John</Name>
<Friend>
<Name>Mike</Name>
</Friend>
</Person>
<Person>
<Name>Mike</Name>
</Person>
</ArrayOfPerson>
Run Code Online (Sandbox Code Playgroud)在上面的代码中,同一个'Mike'对象存在于两个地方,因为对同一个对象有两个引用.
Dar*_*rov 35
XmlSerializer无法实现.您可以使用PreserveObjectReferences属性通过DataContractSerializer实现此目的.你可以看看这篇解释细节的帖子.
这是一个示例代码:
public class Person
{
public string Name;
public Person Friend;
}
class Program
{
static void Main(string[] args)
{
Person p1 = new Person();
p1.Name = "John";
Person p2 = new Person();
p2.Name = "Mike";
p1.Friend = p2;
Person[] group = new Person[] { p1, p2 };
var serializer = new DataContractSerializer(group.GetType(), null,
0x7FFF /*maxItemsInObjectGraph*/,
false /*ignoreExtensionDataObject*/,
true /*preserveObjectReferences : this is where the magic happens */,
null /*dataContractSurrogate*/);
serializer.WriteObject(Console.OpenStandardOutput(), group);
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生以下XML:
<ArrayOfPerson z:Id="1" z:Size="2" xmlns="http://schemas.datacontract.org/2004/07/ToDelete" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Person z:Id="2">
<Friend z:Id="3">
<Friend i:nil="true"/>
<Name z:Id="4">Mike</Name>
</Friend>
<Name z:Id="5">John</Name>
</Person>
<Person z:Ref="3" i:nil="true"/>
</ArrayOfPerson>
Run Code Online (Sandbox Code Playgroud)
现在设置PreserveObjectReferences
为false
构造函数,你会得到这个:
<ArrayOfPerson xmlns="http://schemas.datacontract.org/2004/07/ToDelete" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Person>
<Friend>
<Friend i:nil="true"/>
<Name>Mike</Name>
</Friend>
<Name>John</Name>
</Person>
<Person>
<Friend i:nil="true"/>
<Name>Mike</Name>
</Person>
</ArrayOfPerson>
Run Code Online (Sandbox Code Playgroud)
值得一提的是,以这种方式生成的XML不可互操作,只能使用DataContractSerializer进行反序列化(与BinaryFormatter相同).
您可以使用 ExtendedXmlSerializer。下面是序列化对象引用和循环引用的例子
如果你有一个类:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public Person Boss { get; set; }
}
public class Company
{
public List<Person> Employees { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后使用循环引用创建对象,如下所示:
var boss = new Person {Id = 1, Name = "John"};
boss.Boss = boss; //himself boss
var worker = new Person {Id = 2, Name = "Oliver"};
worker.Boss = boss;
var obj = new Company
{
Employees = new List<Person>
{
worker,
boss
}
};
Run Code Online (Sandbox Code Playgroud)
您必须将 Person 类配置为引用对象:
var serializer = new ConfigurationContainer().ConfigureType<Person>()
.EnableReferences(p => p.Id)
.Create();
Run Code Online (Sandbox Code Playgroud)
最后,您可以序列化您的对象:
var xml = serializer.Serialize(obj);
Run Code Online (Sandbox Code Playgroud)
输出 xml 将如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Company xmlns="clr-namespace:ExtendedXmlSerializer.Samples.ObjectReference;assembly=ExtendedXmlSerializer.Samples">
<Employees>
<Capacity>4</Capacity>
<Person Id="2">
<Name>Oliver</Name>
<Boss Id="1">
<Name>John</Name>
<Boss xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:entity="1" />
</Boss>
</Person>
<Person xmlns:exs="https://extendedxmlserializer.github.io/v2" exs:entity="1" />
</Employees>
</Company>
Run Code Online (Sandbox Code Playgroud)
ExtendedXmlSerializer 支持 .net 4.5 和 .net Core。