проблема при сериализации графов с protobuf.net - PullRequest
1 голос
/ 23 мая 2011

во время игры с недавно выпущенным protobuf.net мы столкнулись с проблемой, показанной в следующем коде:

[ProtoContract]
class Node
{
    public Node()
    {
        ChildLinks = new List<Link>();
        ParentLinks = new List<Link>();
    }

    [ProtoMember(1, IsRequired = true)]
    public string Data { get; set; }

    [ProtoMember(2, IsRequired = true)]
    public List<Link> ChildLinks { get; set; }

    [ProtoMember(3, IsRequired = true)]
    public List<Link> ParentLinks { get; set; }

    public void AddChild(Node child)
    {
        Link link = new Link { Parent = this, Child = child };
        ChildLinks.Add(link);
        child.ParentLinks.Add(link);
    }
}

[ProtoContract]
class Link
{
    [ProtoMember(2, AsReference = true, IsRequired = true)]
    public Node Child { get; set; }

    [ProtoMember(3, AsReference = true, IsRequired = true)]
    public Node Parent { get; set; }
}

public static void Main()
{
    Node node = new Node { Data = "parent" };
    node.AddChild(new Node { Data = "child" });

    using (MemoryStream memStream = new MemoryStream())
    {
        Serializer.Serialize(memStream, node);
        memStream.Position = 0;
        Node deserialized = Serializer.Deserialize<Node>(memStream);

        Link childLink = deserialized.ChildLinks.Single();
        Debug.Assert(ReferenceEquals(childLink, childLink.Child.ParentLinks.Single()));
    }
}

Assert создает исключение ... Наша цель - создать уникальный экземпляр объекта Link в свойствах ChildLinks и ParentLinks. Мы попробовали атрибут AsReference, но он не работал ...

Кто-нибудь знает, как мы могли бы это исправить?

1 Ответ

1 голос
/ 23 мая 2011

Мне все еще нужно оценить воздействие (не то, что нужно сушить, пока моя голова ощущается как сыр), но есть .... проблема с объектом root на графике - значение: потому что я обычно обрабатываю отслеживание ссылок при обходе ассоциации , а в корневом объекте нет никакой связи.Я думаю, что я, вероятно, могу решить эту проблему с помощью некоторого атрибута уровня типа (например, всегда рассматривать как ссылку).

В любом случае, сейчас вы можете обойти это, добавив еще один уровеньк графику (искусственно добавляя ассоциацию), т.е.

static class Program
{
    public static void Main()
    {

        Node node = new Node { Data = "parent" };
        node.AddChild(new Node { Data = "child" });
        using (MemoryStream memStream = new MemoryStream())
        {
            Serializer.Serialize(memStream, new NodeWrapper { Root = node });
            memStream.Position = 0;
            Node deserialized = Serializer.Deserialize<NodeWrapper>(memStream).Root;

            Link childLink = deserialized.ChildLinks.Single();
            Debug.Assert(ReferenceEquals(childLink, childLink.Child.ParentLinks.Single()));
        }
    }
}
[ProtoContract]
class NodeWrapper
{
    [ProtoMember(1, AsReference = true, IsRequired = true)]
    public Node Root {get;set;}
}
...