XamlServices.Save генерирует атрибут x: Name = "__ ReferenceID0", пока существует RuntimeNameProperty - PullRequest
1 голос
/ 19 ноября 2011

У меня проблемы с сериализацией / десериализацией XamlServices.У меня есть этот класс:

[RuntimeNameProperty("Name")]
[ContentProperty("Children")]
public class Node
{
    public Node()
    {

    }

    public string   Name    { get; set; }
    public int      Valeur  { get; set; }

    public Node Parent
    {
        get;
        set;
    }

    public bool HasChildren
    {
        get { return mChildren.Count > 0; }
    }

    public NodeList Children
    {
        get { return mChildren; }
        set { mChildren = value; }
    }

    NodeList mChildren = new NodeList();
}

NodeList - это короткий класс, определенный как:

public class NodeList : IList<Node>
{
    // ... implemented using a List<Node> internally
}

Если я создаю иерархию узлов, например:

Node root = new Node() { Name = "A", Valeur = 2, Parent = null };
root.Children.Add( new Node() { Name = "A1", Valeur = 3, Parent = root } );
root.Children.Add( new Node() { Name = "A2", Valeur = 3, Parent = root } );
root.Children[0].Children.Add( new Node() { Name = "A21", Valeur = 5, Parent = root.Children[0] } );

и я сериализирую его так:

using( TextWriter writer = File.CreateText( "test.xaml" ) )
{
    XamlServices.Save( writer, root );
}

Вот результирующий xaml:

<Node Parent="{x:Null}" x:Name="__ReferenceID1" Name="A" Valeur="2"
   xmlns="clr-namespace:TestCRTP;assembly=TestCRTP"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Node Parent="{x:Reference A}" x:Name="__ReferenceID0" Name="A1" Valeur="3">
        <Node Parent="{x:Reference A1}" Name="A21" Valeur="5">
            <NodeList />
        </Node>
    </Node>
    <Node Parent="{x:Reference A}" Name="A2" Valeur="3">
        <NodeList />
    </Node>
</Node>

Как вы можете видеть, XamlServices генерирует атрибут "__ReferenceID0", где он не должен делатьэто, так как есть атрибут RuntimeNameProperty ... Очевидно, он делает это из-за x: Reference (из-за отношения Parent), но самое смешное, что он даже не использует сгенерированное x: Name !!И, конечно, становится хуже, когда я пытаюсь десериализовать его:

using( TextReader reader = File.OpenText( "test.xaml" ) )
{
    Node node = XamlServices.Load( reader ) as Node;
}

У меня есть ошибка "Свойство" Имя "уже установлено на" Узле "", что логично, так какдействительно, это уже имя ....

Любая подсказка?

1 Ответ

1 голос
/ 19 ноября 2011

Есть только два решения: либо вы должны изменить свойство Name на что-то другое, например XName, либо на любое другое, не являющееся "Name".

Или вам придется отключить родительскую сериализацию,

[DesignerSerializability(DesignerSerializability.Hidden)]
public Node Parent
{
    get;
    set;
}

Но в этом случае вам придется обрабатывать узлы и устанавливать родителей вручную после загрузки графа объектов.

Причина, по которой XAML делает это, заключается в сериализации графов объектов, которые связаны друг с другом, а не просто с деревом. И он использует Name для уникальной идентификации узлов, однако это их внутренняя логика, которая теперь позволяет вам использовать свойство Name, когда оно пытается разрешить именные ссылки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...