Der grundlegende Unterschied zwischen # 1 und # 2 ist, dass sie unterschiedliche XML Schemas erzeugen. Wenn Sie möchten, dass ein Mitglied aus dem Schema Ihres Typs ausgeschlossen wird, verwenden Sie [XmlIgnore]
. Wenn Sie möchten, dass ein Mitglied bedingt hinzugefügt wird, verwenden Sie ShouldSerializeXXX()
oder XXXSpecified
. (Schließlich wird, wie in this answer angegeben, [NonSerialized]
in Option # 3 von XmlSerializer
ignoriert.)
Um den Unterschied zwischen # 1 und # 2, sehen Sie xsd.exe
verwenden Schemata für Ihre Typen zu generieren. Das folgende Schema wird für die Version # 1 erzeugt und unterlässt vollständig Name
Mitglied:
<xs:complexType name="Item" />
Während die folgende für die # 2 bedingt umfasst das Name
Mitglied:
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
</xs:sequence>
Der Unterschied ergibt sich, weil XmlSerializer
und xsd.exe
sowohl Führen Sie statische Analyse statt dynamische Code-Analyse. Keines der beiden Tools kann feststellen, dass die Eigenschaft Name
im Fall # 2 immer übersprungen wird, da beide Tools den Quellcode für ShouldSerializeName()
nicht dekompilieren, um zu beweisen, dass er immer false
zurückgibt. Daher wird Name
im Schema für Version # 2 erscheinen, obwohl es nie in der Praxis erscheint. Wenn Sie dann einen Webdienst erstellen und Ihr Schema mit WSDL veröffentlichen (oder einfach manuell zur Verfügung stellen), werden für diese beiden Typen unterschiedliche Clients generiert - eines ohne Name
Mitglied und eines mit.
Eine zusätzliche Komplexität kann auftreten, wenn die betreffende Eigenschaft einen nicht nullbaren Wertetyp aufweist. Betrachten Sie die folgenden drei Versionen von Item
.Zunächst wird eine Version mit einer bedingungslos Wert Eigenschaft enthalten:
public class Item
{
public int Id { get; set; }
}
Erzeugt das folgende Schema mit Id
immer vorhanden:
<xs:complexType name="Item">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Id" type="xs:int" />
</xs:sequence>
</xs:complexType>
Zweitens eine Version mit einer bedingungslos Wert Eigenschaft ausgeschlossen:
public class Item
{
[XmlIgnore]
public int Id { get; set; }
}
Erzeugt das folgende Schema, das die Id
-Eigenschaft vollständig ausschließt:
<xs:complexType name="Item" />
Und schließlich eine Version mit einer bedingt ausgeschlossen Wert Eigenschaft:
public class Item
{
public int Id { get; set; }
public bool ShouldSerializeId()
{
return false;
}
}
Erzeugt das folgende Schema mit Id
nur bedingt vorhanden:
<xs:complexType name="Item">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Id" type="xs:int" />
</xs:sequence>
</xs:complexType>
Schema # 2 wie erwartet, aber Bekanntmachung Es gibt einen Unterschied zwischen # 1 und # 3: der erste hat während der dritte minOccurs="0"
hat. Der Unterschied tritt auf, weil XmlSerializer
documented ist, um Mitglieder mit null
Werten standardmäßig zu überspringen, aber keine ähnliche Logik für nicht nullable Wertelemente hat. Somit wird die Id
Eigenschaft in Fall # 1 immer serialisiert, und so wird im Schema angezeigt. Nur wenn die bedingte Serialisierung aktiviert ist, wird minOccurs="0"
generiert. Wenn das dritte Schema wiederum ist für die Client-Code-Generierung verwendet wird, eine IdSpecified
Eigenschaft wird den automatisch generierten Code hinzugefügt werden, um zu verfolgen, ob die Id
Eigenschaft tatsächlich während der Deserialisierung aufgetreten:
public partial class Item {
private int idField;
private bool idFieldSpecified;
/// <remarks/>
public int Id {
get {
return this.idField;
}
set {
this.idField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool IdSpecified {
get {
return this.idFieldSpecified;
}
set {
this.idFieldSpecified = value;
}
}
}
Für weitere Einzelheiten über die Bindung an bedingt serialisierte Wertelemente, siehe XML Schema Binding Support: MinOccurs Attribute Binding Support und ShouldSerialize*() vs *Specified Conditional Serialization Pattern.
Also das ist der Hauptunterschied, aber es gibt auch sekundäre Unterschiede, die beeinflussen können, welche Sie sich entscheiden:
[XmlIgnore]
kann nicht in einer abgeleiteten Klasse überschrieben werden, aber ShouldSerializeXXX()
können, wenn sie als virtuelle markiert sein; ein Beispiel finden Sie in here.
Wenn ein Mitglied nicht durch XmlSerializer
serialisiert werden, da es zum Beispiel auf eine Art bezieht, dass lacks a parameterless constructor, dann markiert das Element mit [XmlIgnore]
wird die umschließende Art erlaubt serialisiert werden - während ein ShouldSerializeXXX() { return false; }
Zugabe wird das enthält nicht zulassen, Typ zu serialisieren, da wie zuvor erwähnt XmlSerializer
nur statische Typanalyse durchführt. Z.B. die folgenden:
public class RootObject
{
// This member will prevent RootObject from being serialized by XmlSerializer despite the fact that the ShouldSerialize method always returns false.
// To make RootObject serialize successfully, [XmlIgnore] must be added.
public NoDefaultConstructor NoDefaultConstructor { get; set; }
public bool ShouldSerializeNoDefaultConstructor() { return false; }
}
public class NoDefaultConstructor
{
public string Name { get; set; }
public NoDefaultConstructor(string name) { this.Name = name; }
}
nicht durch XmlSerializer
serialisiert werden.
[XmlIgnore]
ist spezifisch für XmlSerializer
, aber ShouldSerializeXXX()
wird von anderen Serializer einschließlich Json.NET und protobuf-net verwendet.
Wie in den Kommentaren erwähnt, wird beim Umbenennen einer bedingt serialisierten Eigenschaft in Visual Studio der entsprechende Methodenname ShouldSerializeXXX()
nicht automatisch umbenannt, was zu potenziellen Wartungsfehlern führt.
Wenn alle nach Ihrem Standard arbeiten, dann wählen Sie die, die Sie bevorzugen. PS Die 'ShouldSerializeXXX' Version ist eine schreckliche Idee, benutze diese nicht! – DavidG
@DavidG: Con bitte Argument, warum ist es eine schreckliche Idee, 'ShouldSerializeXXX' zu verwenden. – scher
Nun, Sie werden Ihr Modell mit all diesen zusätzlichen Methoden verschmutzen, während ein Attribut nicht. – DavidG