属性不会被序列化到.designer.cs文件中

sth*_*lik 3 c# serialization designer visual-studio-2010

在VS2010中,尽管使用了ShouldSerializeFoo方法,但是控制属性也不会被序列化,而且还有DesignerSerializationVisibility.Visible/Content.

这是代码:

class Class1 : UserControl {
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public string Foo {
        get; set;
    }
    public bool ShouldSerializeFoo() {
        return true;
    }
    public Class1() {
        Foo = "dupa";
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,设计器不会为此属性生成任何内容:

        // 
        // class11
        // 
        this.class11.Location = new System.Drawing.Point(224, 262);
        this.class11.Name = "class11";
        this.class11.Size = new System.Drawing.Size(150, 150);
        this.class11.TabIndex = 2;
        this.class11.Load += new System.EventHandler(this.class11_Load);
Run Code Online (Sandbox Code Playgroud)

Ada*_*son 9

你正在混合序列化方案.设计器序列化(这是DesignerSerializationVisibility为了什么)与实例序列化机制无关(这是ShouldSerializeXXX许多其他功能中的函数).

DesignerSerializationVisibility.Content对于string(或任何其他不可变类型)没有多大意义.设计人员可以将属性的序列化视为三种类型:

  • 没有 - 它从不序列化有关该属性的任何内容
  • 可见 - 它将序列化属性的实际值
  • 内容 - 它将序列化属性值的属性值.

默认情况下,会考虑属性Visible.我意识到我的定义Content可能有点令人困惑.我的意思是这样的:

public class MyControl : Control
{
    public class SomeOptions
    {
        public string Option1 { get; set; }
        public string Option2 { get; set; }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public SomeOptions Options { get; private set; }

    public string Foo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,当这个类被设计器序列化时,它看起来像这样:

// myControl1
this.myControl1.Foo = "value";
this.myControl1.Options.Option1 = "option1";
this.myControl1.Options.Option2 = "option2";
Run Code Online (Sandbox Code Playgroud)

这应该更有意义; 将属性标记为Content表示,而不是序列化属性的实际值(在这种情况下,它将是一个实例SomeOptions),它应该序列化该值的属性值.

所以,回到你的问题,这就是你不想要Content一个string房产的原因.因为strings是不可变的,所以设计师没有什么可以序列化的.将其标记为Visible或完全关闭属性(因为这是默认值).

虽然可以向设计者提供关于是否要序列化特定属性的自定义方向,但这是一个非常复杂(和讨厌)的过程.在简单的方法,虽然是使用DefaultValue属性的财产.如果属性是否应该序列化可以通过将其值与常量进行比较来确定(换句话说,它不依赖于运行时的任何其他内容,如另一个属性的值),您可以像这样装饰属性:

[DefaultValue("foo")]
public string Foo { get; set; }
Run Code Online (Sandbox Code Playgroud)

如果设计者然后看到值Foo等于"foo",那么它根本不会序列化属性.