Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 映射和序列化双向关联_C#_Xml_Serialization - Fatal编程技术网

C# 映射和序列化双向关联

C# 映射和序列化双向关联,c#,xml,serialization,C#,Xml,Serialization,我想,这将是一个微不足道的问题,并会立即找到答案,但不知何故,互联网证明了我的假设是错误的 我有一个包含多个实体的模型,这些实体之间有所有可能的关联(1到1、1到多、多到多、聚合、组合等)。为了简单起见,让我们以这个例子为例。我们有个人课和汽车课。一个人可以拥有多辆车,但一辆车只能属于一个人(因此是一对多关系)。现在,亲自创建一个列表/数组列表来跟踪他/她的汽车将非常简单。不过,我也希望能和车主保持联系。因此,这些类将如下所示: [Serializable] public class Perso

我想,这将是一个微不足道的问题,并会立即找到答案,但不知何故,互联网证明了我的假设是错误的

我有一个包含多个实体的模型,这些实体之间有所有可能的关联(1到1、1到多、多到多、聚合、组合等)。为了简单起见,让我们以这个例子为例。我们有个人课和汽车课。一个人可以拥有多辆车,但一辆车只能属于一个人(因此是一对多关系)。现在,亲自创建一个列表/数组列表来跟踪他/她的汽车将非常简单。不过,我也希望能和车主保持联系。因此,这些类将如下所示:

[Serializable]
public class Person
{
    [XmlElement]
    public List<Car> Cars { get; set; }

    [XmlAttribute]
    public string Name { get; set; }

    public Person()
    {
        Cars = new List<Car>();
    }
}

[Serializable]
public class Car
{
    [XmlElement]
    public Person Owner { get; set; }

    [XmlAttribute]
    public string Type { get; set; }

    public Car()
    {
    }
}
<Person name="John Doe">
  <Cars>
    <Car type="Ford">
      <Owner>
        <Person name="John Doe">
          <Cars>
            <Car type="Ford">
              <Owner>
                <Person name="John Doe">
      ... etc.
[可序列化]
公共阶层人士
{
[XmlElement]
公共列表车辆{get;set;}
[XmlAttribute]
公共字符串名称{get;set;}
公众人士()
{
Cars=新列表();
}
}
[可序列化]
公车
{
[XmlElement]
公共人物所有者{get;set;}
[XmlAttribute]
公共字符串类型{get;set;}
公共汽车
{
}
}
但是,我相信,这种结构会导致Xml文件中出现无限循环,如下所示:

[Serializable]
public class Person
{
    [XmlElement]
    public List<Car> Cars { get; set; }

    [XmlAttribute]
    public string Name { get; set; }

    public Person()
    {
        Cars = new List<Car>();
    }
}

[Serializable]
public class Car
{
    [XmlElement]
    public Person Owner { get; set; }

    [XmlAttribute]
    public string Type { get; set; }

    public Car()
    {
    }
}
<Person name="John Doe">
  <Cars>
    <Car type="Ford">
      <Owner>
        <Person name="John Doe">
          <Cars>
            <Car type="Ford">
              <Owner>
                <Person name="John Doe">
      ... etc.

... 等
我甚至尝试过,在序列化过程中,我得到了“您需要将XmlChoiceIdentifierAttribute添加到‘所有者’成员”的异常

因此,我有几个问题: 1.有没有办法防止序列化中的循环? 2.如果不是,我是否必须为每个类编写自己的序列化程序?
3.这个映射可以吗?还是有其他/更好的方法?我考虑过一个中心的“Mapper”类,它将根据ID返回所需的对象。。。不过,这也可以通过SQL来实现。我希望避免使用SQL(因为它使应用程序轻量级)。

XmlSerializer
是一个树序列化程序,而不是一个图形序列化程序。最好的办法是避免序列化过程中的向后导航,例如:

[XmlIgnore]
public Person Owner { get; set; }
(“父项”和“所有者”几乎总是向后导航)

不幸的是,
XmlSerializer
不支持序列化后回调,否则可以添加如下内容:

[WhateverOnAfterDeserialized]
public void OnAfterDeserialized(...) {
    foreach(var car in cars) car.Owner = this;
}
其他一些序列化程序确实支持序列化回调,但根据该标记,这些其他序列化程序可能也支持完整的图序列化。例如,
DataContractSerializer
可以支持回调和完整图,但它提供的对xml的控制要少得多

另一个选项是使用自定义集合类型,在添加/删除时维护父属性;例如:

public class Person
{
    private readonly CarCollection cars;
    public Person() {
        cars = new CarCollection(this);
    }
    [XmlElement]
    public CarCollection Cars { get { return cars; } } 

    ...
}
使用(在
CarCollection
):

就我个人而言,我认为这可能是矫枉过正

另一种选择是简单地添加一个修复方法,在反序列化后调用该方法,该方法执行任何必要的操作(并向下级联):

请注意,您必须手动调用它

最后,请注意,
[Serializable]
对于
XmlSerializer
不是必需的