Свойство производной коллекции не сериализовано в конструкторе - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть класс, производный от коллекции, которая имеет свойство MyString, т.е.

  public class CollectionItem
  {
    public bool MyBoolean { get; set; }

    public int MyInteger { get; set; }
  }

  public class MyCollection : List<CollectionItem>
  {
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public string MyString { get; set; }

    public MyCollection()
    {
      MyString = "Hello";
    }
  }

Эта коллекция является частью простого DummyControl, т.е.

  public class DummyControl : System.Windows.Forms.Control
  {
    protected override void OnPaint(PaintEventArgs e)
    {
      base.OnPaint(e);
      e.Graphics.FillRectangle(System.Drawing.Brushes.Yellow, e.ClipRectangle);
    }

    public DummyControl() 
    {
      MyCollection = new MyCollection();

      for (int i = 0; i < 3; i++)
      {
        CollectionItem item = new CollectionItem();
        item.MyInteger = i;
        item.MyBoolean = i > 1;
        MyCollection.Add(item);
      }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public MyCollection MyCollection { get; set; }
  }

Когда я помещаю этот DummyControl в форму Windows, все, как и ожидалось, сериализуется в Designer Form, кроме свойства MyString - вот что я получаю:

  // 
  // dummyControl1
  // 
  this.dummyControl1.Location = new System.Drawing.Point(66, 62);
  collectionItem1.MyBoolean = false;
  collectionItem1.MyInteger = 0;
  collectionItem2.MyBoolean = false;
  collectionItem2.MyInteger = 1;
  collectionItem3.MyBoolean = true;
  collectionItem3.MyInteger = 2;
  this.dummyControl1.MyCollection.Add(collectionItem1);
  this.dummyControl1.MyCollection.Add(collectionItem2);
  this.dummyControl1.MyCollection.Add(collectionItem3);
  this.dummyControl1.Name = "dummyControl1";
  this.dummyControl1.Size = new System.Drawing.Size(338, 266);
  this.dummyControl1.TabIndex = 0;
  this.dummyControl1.Text = "dummyControl1";

Может кто-нибудь сказать, что мне еще нужно сделать, чтобы свойство MyString было сериализовано в Form Designer?

1 Ответ

0 голосов
/ 11 ноября 2018

Сериализатор коллекции CodeDom по умолчанию не сериализует свойства коллекции. Вы можете создать собственный сериализатор, производный от CodeDomSerializer. Затем зарегистрируйте пользовательский сериализатор для вашего класса:

[DesignerSerializer(typeof(MyCollectionSerializer), typeof(CodeDomSerializer))]
public class MyCollection : List<CollectionItem>

MyCollectionSerializer

Этот сериализатор сериализует MyString свойство MyCollection:

using System.CodeDom;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
public class MyCollectionSerializer : CodeDomSerializer
{
    public override object Serialize(IDesignerSerializationManager manager, object value)
    {
        var baseSerializer = (CodeDomSerializer)manager.GetSerializer(
            typeof(MyCollection).BaseType, typeof(CodeDomSerializer));
        var statements = (CodeStatementCollection)baseSerializer.Serialize(manager, value);
        var property = TypeDescriptor.GetProperties(value)[nameof(MyCollection.MyString)];
        if (property.ShouldSerializeValue(value))
        {
            var targetObject = base.GetExpression(manager, value);
            var cpre = new CodePropertyReferenceExpression(targetObject, property.Name);
            var cpe = new CodePrimitiveExpression(property.GetValue(value));
            var cas = new CodeAssignStatement(cpre, cpe);
            statements.Add(cas);
        }
        return statements;
    }
} 

Тогда свойство MyString также будет сериализовано:

// 
// dummyControl1
// 
...
this.dummyControl1.MyCollection.Add(collectionItem1);
this.dummyControl1.MyCollection.Add(collectionItem2);
this.dummyControl1.MyCollection.Add(collectionItem3);
this.dummyControl1.MyCollection.MyString = "Hello";
...
...