Сложность с сохранением коллекции, которая ссылается на внутреннее свойство во время разработки в Winforms и .net - PullRequest
4 голосов
/ 11 марта 2010

Самый простой способ объяснить эту проблему - показать вам код:

Public Interface IAmAnnoyed
End Interface

Public Class IAmAnnoyedCollection
    Inherits ObjectModel.Collection(Of IAmAnnoyed)
End Class

Public Class Anger
    Implements IAmAnnoyed
End Class

Public Class MyButton
    Inherits Button

Private _Annoyance As IAmAnnoyedCollection
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property Annoyance() As IAmAnnoyedCollection
    Get
        Return _Annoyance
    End Get
End Property

Private _InternalAnger As Anger
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property InternalAnger() As Anger
    Get
        Return Me._InternalAnger
    End Get
End Property

Public Sub New()
    Me._Annoyance = New IAmAnnoyedCollection
    Me._InternalAnger = New Anger
    Me._Annoyance.Add(Me._InternalAnger)
End Sub

End Class

И вот код, который генерирует дизайнер:

Private Sub InitializeComponent()
    Dim Anger1 As Anger = New Anger
    Me.MyButton1 = New MyButton
    '
    'MyButton1
    '
    Me.MyButton1.Annoyance.Add(Anger1)
    // Should be: Me.MyButton1.Annoyance.Add(Me.MyButton1.InternalAnger)
    '
    'Form1
    '
    Me.Controls.Add(Me.MyButton1)

End Sub

Я добавил комментарий к вышесказанному, чтобы показать, как должен был генерироваться код. Теперь, если я обойдусь без интерфейса и просто получу коллекцию Anger, он будет сохранен правильно.

Есть идеи?

Обновление 1

Мне это надоело. Эта проблема была связана с сохранением коллекции интерфейсов, но теперь при дальнейшем тестировании она не работает для обычной коллекции. Вот еще один простой код:

Public Class Anger
End Class

Public Class MyButton
    Inherits Button

Private _Annoyance As List(Of Anger)
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property Annoyance() As List(Of Anger)
    Get
        Return _Annoyance
    End Get
End Property

Private _InternalAnger As Anger
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property InternalAnger() As Anger
    Get
        Return Me._InternalAnger
    End Get
End Property

Public Sub New()
    Me._Annoyance = New List(Of Anger)
    Me._InternalAnger = New Anger
    Me._Annoyance.Add(Me._InternalAnger)
End Sub

End Class

Дизайнер испортил постоянный код так же, как исходная проблема.

Обновление 2

Я выяснил, что происходит. Я задавался вопросом, почему иногда это работает, а не другие. Это сводится к имени, которое я даю внутреннему свойству и коллекции.

Если я переименую свойство «Раздражение» в «WTF», оно будет правильно сериализовано, поскольку «WTF» в алфавитном порядке после имени коллекции - «InternalAnger».

Похоже, что сериализатор создает экземпляры объектов в алфавитном порядке и требует, чтобы мое внутреннее свойство было создано к моменту создания коллекции.

Я могу исправить это с помощью переименования, но это хак, и я боюсь, что написание собственного сериализатора - большая работа, которой я никогда раньше не делал.

Есть идеи?

Обновление 3

Я ответил на вопрос взломом. Я вполне уверен в этом, если MS не изменит способ кодирования, сериализующий код конструктора.

Ответы [ 4 ]

0 голосов
/ 13 марта 2010

Как я уже говорил в ОП, проблема сводится к названию, которое я даю внутреннему свойству и коллекции.

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

Я делаю это, сохраняя исходное имя свойства «InternalProperty», но отключаю сериализацию и отсылаю его к прокси-свойству с искусным именем и сериализацией.

Private _InternalProperty
Public ReadOnly Property InternalProperty
    Get
        Return Me._ProxyInternalProperty 
    End Get
End Property

<Browsable(False), EditorBrowsable(Never), DesignerSerializationVisibility(Content)> _
Public ReadOnly Property _ProxyInternalProperty
    Get
        Return Me._InternalProperty
    End Get
End Property

Это взлом, но лучше, чем переименование моего свойства в AInternalProperty. Кроме того, пользователь никогда не увидит _ProxyInternalProperty, потому что он скрыт, и даже если он его обнаружил, ссылаться на него не опасно.

0 голосов
/ 12 марта 2010

Может ли быть проблема в том, что вы добавляете элемент в коллекцию в конструкторе элемента управления, который дизайнер затем отдельно сериализует?

Я думаю, что ваш закомментированный код "должен был быть сгенерирован" также неверен. Так как конструктор элемента управления добавляет InternalAnger в коллекцию, зачем вам также видеть его в InitializeComponent?

0 голосов
/ 12 марта 2010

Снимите DesignerSerializationVisibility.Content со свойства InternalAnger, и оно должно работать так, как вы ожидаете.

Например (C #, но идея та же самая)

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        this.InternalAnger = new Anger();
        this.InternalAnger.SomeValue = 2;
        this.Angers.Add(this.InternalAnger);
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public List<Anger> Angers
    {
        get { return this.list; }
    }

    public Anger InternalAnger { get; set; }

    private List<Anger> list = new List<Anger>();
    private Anger _InternalAnger;
}

public class Anger
{
    public Anger() { }

    public int SomeValue { get; set; }
}

генерирует: * +1008 *

WindowsFormsApplication1.Anger anger1 = new WindowsFormsApplication1.Anger();
anger1.SomeValue = 2;
this.userControl11.Angers.Add(anger1);
this.userControl11.InternalAnger = anger1;

что, я думаю, то, что вы хотите.

0 голосов
/ 11 марта 2010

Я здесь немного не в себе, но разве у вас не должно быть частного сеттера для этого свойства только для чтения? Я имею в виду, он не может сериализовать то, что не может установить, правильно?

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