C#如何解决圆形对象引用

时间:2010-11-24 14:53:34

标签: c# serialization object

我遇到了我认为可能是我的代码设计的主要问题,我希望有人可以向我解释我将如何解决这个问题。

我有2个类,每个类都有另一个类的属性创建循环引用。我计划序列化这些类并使用XSLT格式化输出,但我假设由于循环引用而失败。

实施例

public class Book
{
  public BookShop TheShop = new BookShop();
}
public class BookShop
{
  list<Book> Books = new list<Book>();
}

因此,从这个例子中,每本书都会出现在书店中,每个书店都会有很多书。如果我序列化书店,它将序列化每本书,然后序列化书店等等。我应该怎么处理这个?

5 个答案:

答案 0 :(得分:6)

使用属性标记TheShop以防止其序列化。

[XmlIgnore]使用默认序列化程序。

http://www.codeproject.com/KB/XML/GameCatalog.aspx

可能只是您示例的问题,而不是您的真实代码:不要使用公共字段,而是使用属性。我认为XmlSerializer甚至没有序列化公共字段。

答案 1 :(得分:1)

[XmlIgnore]添加到TheShop属性,以防止序列化。

然后,您可以在反序列化时手动设置它。

答案 2 :(得分:1)

最佳做法是让BookShop类实现一个接口(IBookShop),然后让Book类存储接口而不是具体类。您还应该将BookShop变成Book类中的属性:

public class Book
{
    public Book(IBookShop bookShop)
    {
        TheStop = bookShop;
    }
    [XmlIgnore]
    public IBookShop TheShop { get; set; }
}
public interface IBookShop 
{
    void SomeMethod();
}
public class BookShop : IBookShop
{
    list<Book> Books = new list<Book>();
    public void SomeMethod()
    {
    }
}

答案 3 :(得分:0)

如果您要使用System.Xml.Serialization.XmlSerializer,则应使用TheShop装饰System.Xml.Serialization.XmlIgnoreAttribute

public class Book
{
  [System.Xml.Serialization.XmlIgnore]
  public BookShop TheShop;
}

也就是说,假设BookShop是您希望序列化的根对象。 MSDN

答案 4 :(得分:0)

首先,你需要检查这是否真的是一个问题。如果你有一本书时总是关心书店,并且你总是关心书店所有的书籍,那么将整个图表序列化是完全明智的。这不会导致无限循环,因为序列化使用标识符来指示对已经序列化的对象的引用(如果在 types <中使用循环引用对图进行XML序列化,则会出现错误/ strong>,但这是一个错误而不是XML序列化问题所固有的错误,因为可以解决它的事实证明,请参阅Why do I get a "System.StackOverflowException was unhandled " exception when serializing?

所以,也许你根本不想在这里做任何事情,你就像你一样好。

否则,问题是 - 你想要序列化什么?到目前为止,大多数建议都是不对TheShop属性进行序列化。这可能没问题,或者如果您以后需要访问该商店,则可能没用。

如果你有每种商店的某种标识符(id号,uri),那么你可能会记忆 - 访问TheShop首先查看私有_theShop是否为空,如果是是,根据该标识符将相关对象加载到_theShop。然后你只需要序列化标识符,而不是完整的对象。

最后,如果您使用XSLT将输出格式化为其他规范(无论是用于显示XHTML还是其他规范),您可能会发现只需滚动自己的XML序列化就更简单了。虽然这在许多方面都是一项更复杂的任务,但序列化生成的XML对于重新格式化显示并不是特别方便,这可能意味着整体而言这种方式更简单。实际上,如果这是序列化的唯一原因(您永远不会从生成的XML中反序列化)那么它可能会容易得多,因为您只需要考虑显示所需的XML,而不必担心其他任何问题。因此,序列化可能不是最好的方法,而只是ToXml()方法或另一个类中的WriteBookToXml()方法。