C# 循环引用的DataContract序列化对于集合的第一项工作得太深,对于其余项工作得太精细
我有两个类相互参照:C# 循环引用的DataContract序列化对于集合的第一项工作得太深,对于其余项工作得太精细,c#,serialization,datacontract,C#,Serialization,Datacontract,我有两个类相互参照: [DataContract(IsReference = true)] public class Student { [DataMember] public int Id { get; set; } [DataMember] public string Name { get; set; } [DataMember] public string Surname { get; set; } [DataMember]
[DataContract(IsReference = true)]
public class Student
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Surname { get; set; }
[DataMember]
public List<Course> Courses { get; set; }
public Student()
{
Courses = new List<Course>();
}
}
[DataContract(IsReference = true)]
public class Course
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public List<Student> Students { get; set; }
public Course()
{
Students = new List<Student>();
}
}
[DataContract(IsReference=true)]
公立班学生
{
[数据成员]
公共int Id{get;set;}
[数据成员]
公共字符串名称{get;set;}
[数据成员]
公共字符串姓氏{get;set;}
[数据成员]
公共列表课程{get;set;}
公立学生()
{
课程=新列表();
}
}
[DataContract(IsReference=true)]
公共课
{
[数据成员]
公共int Id{get;set;}
[数据成员]
公共字符串名称{get;set;}
[数据成员]
公共列表学生{get;set;}
公共课程()
{
学生=新列表();
}
}
我想序列化4个学生实体,每个实体都附带了一些课程。序列化之后,只有第一个学生实体显示为非空。更重要的是,它有太多的参考水平。所有其他学生实体均为空:
<GetStudentsResult
xmlns:a="http://schemas.datacontract.org/2004/07/WcfService2"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"
z:Id="i1">
<a:Courses>
<a:Course z:Id="i2">
<a:Id>1</a:Id>
<a:Name>Operation Systems</a:Name>
<a:Students>
<a:Student z:Ref="i1"/>
<a:Student z:Id="i3">
<a:Courses>
<a:Course z:Ref="i2"/>
<a:Course z:Id="i4">
<a:Id>2</a:Id>
<a:Name>Algorithmes and data structures</a:Name>
<a:Students>
<a:Student z:Ref="i3"/>
<a:Student z:Id="i5">
<a:Courses>
<a:Course z:Ref="i4"/>
<a:Course z:Id="i6">
<a:Id>3</a:Id>
<a:Name>Basics of HTML and CSS</a:Name>
<a:Students>
<a:Student z:Ref="i1"/>
<a:Student z:Id="i7">
<a:Courses>
<a:Course z:Ref="i2"/>
<a:Course z:Ref="i6"/>
</a:Courses>
<a:Id>3</a:Id>
<a:Name>Oleg</a:Name>
<a:Surname>Kuznetsov</a:Surname>
</a:Student>
<a:Student z:Ref="i5"/>
</a:Students>
</a:Course>
</a:Courses>
<a:Id>4</a:Id>
<a:Name>Olga</a:Name>
<a:Surname>Petrova</a:Surname>
</a:Student>
</a:Students>
</a:Course>
</a:Courses>
<a:Id>2</a:Id>
<a:Name>Maria</a:Name>
<a:Surname>Vasilyeva</a:Surname>
</a:Student>
<a:Student z:Ref="i7"/>
</a:Students>
</a:Course>
<a:Course z:Ref="i6"/>
</a:Courses>
<a:Id>1</a:Id>
<a:Name>Egor</a:Name>
<a:Surname>Ivanov</a:Surname>
</a:Student>
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"
z:Ref="i3"/>
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"
z:Ref="i7"/>
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"
z:Ref="i5"/>
</GetStudentsResult>
1.
操作系统
2.
算法和数据结构
3.
HTML和CSS的基础知识
3.
奥列格
库兹涅佐夫
4.
奥尔加
佩特罗瓦
2.
玛丽亚
瓦西里耶娃
1.
伊戈尔
伊万诺夫
以下是我的代码,填写学生和课程集:
Student s1 = new Student { Id = 1, Name = "Egor", Surname = "Ivanov" };
Student s2 = new Student { Id = 2, Name = "Maria", Surname = "Vasilyeva" };
Student s3 = new Student { Id = 3, Name = "Oleg", Surname = "Kuznetsov" };
Student s4 = new Student { Id = 4, Name = "Olga", Surname = "Petrova" };
context.Students.Add(s1);
context.Students.Add(s2);
context.Students.Add(s3);
context.Students.Add(s4);
Course c1 = new Course
{
Id = 1,
Name = "Operation Systems",
Students = new List<Student>() { s1, s2, s3 }
};
Course c2 = new Course
{
Id = 2,
Name = "Algorithmes and data structures",
Students = new List<Student>() { s2, s4 }
};
Course c3 = new Course
{
Id = 3,
Name = "Basics of HTML and CSS",
Students = new List<Student>() { s3, s4, s1 }
};
context.Courses.Add(c1);
context.Courses.Add(c2);
context.Courses.Add(c3);
Student s1=新学生{Id=1,Name=“Egor”,Name=“Ivanov”};
学生s2=新学生{Id=2,Name=“Maria”,姓氏=“Vasilyeva”};
学生s3=新学生{Id=3,Name=“Oleg”,姓氏=“Kuznetsov”};
学生s4=新学生{Id=4,Name=“Olga”,姓氏=“Petrova”};
上下文。学生。添加(s1);
上下文。学生。添加(s2);
上下文。学生。添加(s3);
上下文。学生。添加(s4);
课程c1=新课程
{
Id=1,
Name=“操作系统”,
学生=新列表(){s1,s2,s3}
};
课程c2=新课程
{
Id=2,
Name=“算法和数据结构”,
学生=新列表(){s2,s4}
};
课程c3=新课程
{
Id=3,
Name=“HTML和CSS的基础知识”,
学生=新列表(){s3,s4,s1}
};
上下文。课程。添加(c1);
上下文。课程。添加(c2);
上下文。课程。添加(c3);
请告知。您看到的不是bug。数据协定序列化程序的功能从不在XML文件中创建,只创建向后引用。让我们举一个简单的例子:
[DataContract(IsReference = true, Namespace="")]
public class Item
{
[DataMember]
public int Id { get; set; }
[DataMember]
public Item SubItem { get; set; }
}
public class TestClass
{
public static void TestSimple()
{
var item1 = new Item { Id = 1 };
var item2 = new Item { Id = 2 };
item1.SubItem = item2;
var xml = DataContractSerializerHelper.GetXml(new[] { item1, item2 });
Debug.WriteLine(xml);
}
}
此测试用例创建的XML如下所示:
<ArrayOfItem xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Item z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Id>1</Id>
<SubItem z:Id="i2">
<Id>2</Id>
<SubItem i:nil="true" />
</SubItem>
</Item>
<Item z:Ref="i2" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" />
</ArrayOfItem>
不幸的是,data contact序列化程序没有这样做
您可以看到,通过缩进XML,所有学生都被正确地包括在内——除了第一个学生之外的所有学生都作为第一个学生的课程列表的嵌套元素。随后出现的事件仅为引用:
<GetStudentsResult xmlns:a="http://schemas.datacontract.org/2004/07/WcfService2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="i1">
<a:Courses>
<a:Course z:Id="i2">
<a:Id>1</a:Id>
<a:Name>Operation Systems</a:Name>
<a:Students>
<a:Student z:Ref="i1" />
<a:Student z:Id="i3">
<a:Courses>
<a:Course z:Ref="i2" />
<a:Course z:Id="i4">
<a:Id>2</a:Id>
<a:Name>Algorithmes and data structures</a:Name>
<a:Students>
<a:Student z:Ref="i3" />
<a:Student z:Id="i5">
<a:Courses>
<a:Course z:Ref="i4" />
<a:Course z:Id="i6">
<a:Id>3</a:Id>
<a:Name>Basics of HTML and CSS</a:Name>
<a:Students>
<a:Student z:Ref="i1" />
<a:Student z:Id="i7">
<a:Courses>
<a:Course z:Ref="i2" />
<a:Course z:Ref="i6" />
</a:Courses>
<a:Id>3</a:Id>
<a:Name>Oleg</a:Name>
<a:Surname>Kuznetsov</a:Surname>
</a:Student>
<a:Student z:Ref="i5" />
</a:Students>
</a:Course>
</a:Courses>
<a:Id>4</a:Id>
<a:Name>Olga</a:Name>
<a:Surname>Petrova</a:Surname>
</a:Student>
</a:Students>
</a:Course>
</a:Courses>
<a:Id>2</a:Id>
<a:Name>Maria</a:Name>
<a:Surname>Vasilyeva</a:Surname>
</a:Student>
<a:Student z:Ref="i7" />
</a:Students>
</a:Course>
<a:Course z:Ref="i6" />
</a:Courses>
<a:Id>1</a:Id>
<a:Name>Egor</a:Name>
<a:Surname>Ivanov</a:Surname>
</a:Student>
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Ref="i3" />
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Ref="i7" />
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Ref="i5" />
</GetStudentsResult>
1.
操作系统
2.
算法和数据结构
3.
HTML和CSS的基础知识
3.
奥列格
库兹涅佐夫
4.
奥尔加
佩特罗瓦
2.
玛丽亚
瓦西里耶娃
1.
伊戈尔
伊万诺夫
如果您使用
DataContractSerializer
反序列化该XML,您将发现学生和课程的图形与原始图形的拓扑结构相同,并且已正确还原。您能否共享生成您正在序列化的GetStudentsResult
的代码?我想这是一个人工测试用例?完成了。是的,这是一个人工脚本谢谢,你知道我应该如何修改Web引用客户端部分中的反序列化方法吗?如果你在客户端类上有相同的[DataContract(IsReference=true)]
,它应该可以正常工作。不是吗?客户端类是在reference.cs中自动生成的,它不包含此属性。奇怪的是,服务器有DataContract序列化,但客户端有XML反序列化,甚至考虑到它的类是使用服务器生成的。@RomanPrykhodko-我不确定为什么自动类在您这方面缺少此功能-我不容易在家里复制它。由scvutil.exe创建的.xsd文件肯定包含必需的元素。我建议具体询问另一个问题,说明为什么会发生这种情况,例如,使用“Add Service Reference”生成的类中缺少“IsReference=true”,并详细说明如何重现该问题。
<GetStudentsResult xmlns:a="http://schemas.datacontract.org/2004/07/WcfService2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="i1">
<a:Courses>
<a:Course z:Id="i2">
<a:Id>1</a:Id>
<a:Name>Operation Systems</a:Name>
<a:Students>
<a:Student z:Ref="i1" />
<a:Student z:Id="i3">
<a:Courses>
<a:Course z:Ref="i2" />
<a:Course z:Id="i4">
<a:Id>2</a:Id>
<a:Name>Algorithmes and data structures</a:Name>
<a:Students>
<a:Student z:Ref="i3" />
<a:Student z:Id="i5">
<a:Courses>
<a:Course z:Ref="i4" />
<a:Course z:Id="i6">
<a:Id>3</a:Id>
<a:Name>Basics of HTML and CSS</a:Name>
<a:Students>
<a:Student z:Ref="i1" />
<a:Student z:Id="i7">
<a:Courses>
<a:Course z:Ref="i2" />
<a:Course z:Ref="i6" />
</a:Courses>
<a:Id>3</a:Id>
<a:Name>Oleg</a:Name>
<a:Surname>Kuznetsov</a:Surname>
</a:Student>
<a:Student z:Ref="i5" />
</a:Students>
</a:Course>
</a:Courses>
<a:Id>4</a:Id>
<a:Name>Olga</a:Name>
<a:Surname>Petrova</a:Surname>
</a:Student>
</a:Students>
</a:Course>
</a:Courses>
<a:Id>2</a:Id>
<a:Name>Maria</a:Name>
<a:Surname>Vasilyeva</a:Surname>
</a:Student>
<a:Student z:Ref="i7" />
</a:Students>
</a:Course>
<a:Course z:Ref="i6" />
</a:Courses>
<a:Id>1</a:Id>
<a:Name>Egor</a:Name>
<a:Surname>Ivanov</a:Surname>
</a:Student>
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Ref="i3" />
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Ref="i7" />
<a:Student xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Ref="i5" />
</GetStudentsResult>