2

Das Problem, das ich bin vor ist, dass, wenn ich habe eine Klasse mit einer Eigenschaft mit einem Standardwert wie folgt aus:Gibt es eine Möglichkeit, "ShouldSerialize [PropertyName]" für eine Property einer Property zu verwenden?

public class Border { 
    public Border() { 
     InitializeAdornment(); 
    } 

    [DefaultValue(true)] 
    public bool Visible { 
     get; 
     set; 
    } 

    private void InitializeAdornment() { 
     Visible = true; 
     // Some initialization code here that don't do anything with the property... 
    } 
} 

Und es dann als eine Eigenschaft eines Usercontrol mit DesignerSerializationVisibility.Content Attribut verwenden Sie darauf wie folgt aus:

public class Label : HitAbleControl, IText, IBorder { 
    public Label() { 
     InitializeAdornments(); 
    } 

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    public Border Border { 
     get { 
      return __border; 
     } 
     set { 
      __border = value; 
     } 
    } 

    private Border __border; 

    private void InitializeAdornments() { 
     Border = new Border { 
      Visible = false 
     }; 
     // Some initialization code here that don't do anything with the property... 
    } 
} 

Wenn ich die label1.Border.Visible = true mit dem Visual Studio-Designer einstellen, wird es nicht serialisiert, aber es sollte als der Standardwert sollte in diesem Fall falsch und nicht wahr sein.

Ich weiß, dass ich die Border Klasse, wenn der Standardwert immer serialisiert ändern könnte oder sollte wahr oder falsch sein, zu überprüfen, aber ich würde gerne wissen, ob es so etwas wie ein ShouldSerialize[PropertyName] auf eine Eigenschaft einer Immobilie oder eine weitere Problemumgehung für dieses Serialisierungsproblem, ohne den Serializer zu ändern.

Ich suchte stundenlang versucht, dieses Problem zu lösen, ohne an eine CodeDomSerializer zu appellieren, oder zumindest zu verstehen, warum der Visual Studio Designer dies nicht serialisieren.

Jede Hilfe wird geschätzt, danke!

+0

Brauchen Sie wirklich die 'Border'-Eigenschaft, die öffentlich einstellbar ist? –

+0

@Ivan Stoev In meinem ursprünglichen Code implementiert die Label-Klasse INotifyPropertyChanged, der Einfachheit halber habe ich es so geändert, dass nur das Backing-Feld hier steht – LoRdPMN

+0

INPC ist nicht essentiell, meine Frage war, ob es von außen einstellbar sein sollte. Wenn Sie Klasseninstanzen haben, legen Sie sie normalerweise intern in einem Konstruktor fest und lassen nur deren Eigenschaften von außen einstellbar sein. Ich frage, weil es wichtig ist. –

Antwort

1

Lassen Sie mich zuerst feststellen, dass es keine ShouldSerialize[PropertyName] oder andere Standardmechanismen zur Steuerung des Verhaltens der verschachtelten Objekteigenschaft gibt.

Was Sie verlangen, kann getan werden, erfordert aber einen zusätzlichen Status innerhalb der enthaltenen Klasse. Es könnte einfacher gewesen sein, wenn Sie keinen öffentlichen Setter zur Verfügung gestellt hätten, also können Sie eine Art von Owner-Interface oder etwas, das aufgerufen werden soll, aus der Klasse Border übergeben. Da dies keine Option zu sein scheint, bedarf es zusätzlicher Arbeit, da der übergebene Wert im Setter geklont wird.

Der springende Punkt ist, einen Standardwert als Klasseneigenschaft und nicht als statische Konstante zu haben. Beachten Sie, dass es egal ist, ob Sie den Wert über Designer oder Code festlegen. Der Serializer verwendet DefaultValueAttribute, um festzustellen, ob der Wert serialisiert werden muss oder nicht. Btw, der einfachste Ansatz könnte sein, dieses Attribut zu entfernen, fügen Sie eine bool Methode namens ShouldSerializeVisible und zurück immer true. Hier ist eine erweiterte Implementierung:

[TypeConverter(typeof(ExpandableObjectConverter))] 
public class Border 
{ 
    public Border() 
    { 
     InitializeAdornment(); 
    } 

    public Border Clone() { return (Border)MemberwiseClone(); } 

    public bool Visible { get; set; } 

    private bool ShouldSerializeVisible() { return Visible != DefaultVisible; } 
    private void ResetVisible() { Visible = DefaultVisible; } 

    [Browsable(false)] 
    [RefreshProperties(RefreshProperties.All)] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
    public bool DefaultVisible { get; set; } 

    private void InitializeAdornment() 
    { 
     Visible = DefaultVisible = true; 
     // Some initialization code here that don't do anything with the property... 
    } 
} 

Notierte die DefaultValueAttribute entfernt und ersetzt mit eigenen ShouldSerialize[PropertyName] und Reset[PropertyName] Methoden sowie DefaultVisible Instanz Mitglied.

Die Immobilie in Ihrer Label Klasse wird:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
public Border Border 
{ 
    get { return __border; } 
    set 
    { 
     if (value != null) 
     { 
      value = value.Clone(); 
      value.DefaultVisible = false; 
     } 
     __border = value; 
    } 
} 

Der Nachteil ist, dass die übergebene Border Instanz innerhalb des Setter geklont werden muß.

+0

IMO, der Nachteil des Designers immer Serialisierung der Eigenschaft ist akzeptabler als der Nachteil der Klonen der Instanz und mit einer anderen Eigenschaft zu sagen, den Standardwert zu berücksichtigen, so dass ich endete mit einem 'private bool ShouldSerializeVisible() => true; '. Meine kleine Hoffnung war eine Möglichkeit, dem Designer auf eine deklarative Art und Weise zu sagen, aber wie Sie gesagt haben, gibt es nicht. Also werde ich als Antwort markieren, wie du die einzig möglichen Wege angegeben hast. Danke für die Hilfe! – LoRdPMN

Verwandte Themen