#1と#2との間の基本的な違いは、それらが異なるものを生成することです。XML Schemasタイプのスキーマからメンバーを除外するには、[XmlIgnore]
を使用します。条件付きでメンバーを含める場合は、ShouldSerializeXXX()
またはXXXSpecified
を使用します。 (最後に、オプション#3にthis answer、[NonSerialized]
に述べたようにXmlSerializer
によって無視されます。)
は#1と#2との違いを確認するには、あなたのタイプのためのスキーマを生成するためにxsd.exe
を使用することができます。次のスキーマは、バージョン#1に対して生成及び完全Name
部材省略されている:
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
</xs:sequence>
差が原因XmlSerializer
とxsd.exe
両方を生じる:#2については、次の条件付きName
部材を含むが
<xs:complexType name="Item" />
をダイナミックコード分析ではなく、スタティックタイプ分析を実行してください。いずれのツールもShouldSerializeName()
のソースコードを逆コンパイルしようとしないため、常にfalse
を返すため、ケース#2のName
プロパティは常にスキップされると判断できません。したがって、Name
は、実際には現れないにもかかわらずバージョン#2のスキーマに現れます。その後、Webサービスを作成してWSDLでスキーマを公開する(または単に手動で利用できるようにする)と、Name
のメンバーが1つで、もう1つでは、この2つのタイプの異なるクライアントが生成されます。
問題のプロパティがnull値ではない値型の場合、さらに複雑になる可能性があります。 Item
の次の3つのバージョンを検討してください。まず、無条件に含まれる値プロパティでバージョン:
public class Item
{
public int Id { get; set; }
}
はId
と常に存在次のスキーマを生成する:第二
<xs:complexType name="Item">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Id" type="xs:int" />
</xs:sequence>
</xs:complexType>
、無条件に除外値プロパティでバージョン:
public class Item
{
[XmlIgnore]
public int Id { get; set; }
}
Id
プロパティを完全に省略した次のスキーマを生成します。
<xs:complexType name="Item" />
そして最後に、条件付きで除外valueプロパティを持つバージョン:
public class Item
{
public int Id { get; set; }
public bool ShouldSerializeId()
{
return false;
}
}
はId
条件付きでのみ存在して、次のスキーマを生成します:予想通り
<xs:complexType name="Item">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Id" type="xs:int" />
</xs:sequence>
</xs:complexType>
スキーマ#2ですが、予告#1と#3の間に違いがあります。最初は、3番目はminOccurs="0"
です。この違いは、デフォルトでnull
の値を持つメンバーをスキップするためにXmlSerializer
がdocumentedであるが、null値のない値のメンバーには類似のロジックがないために発生します。したがって、#1の場合Id
プロパティは常にシリアル化されるため、がスキーマに示されます。条件付きシリアル化が有効な場合のみ、minOccurs="0"
が生成されます。第三スキーマは、クライアントコードの生成に使用される順番になっている場合、IdSpecified
プロパティがId
プロパティは、実際に直列化復元中に発生したかどうかを追跡するために、自動生成されたコードに追加されます:への結合の詳細については
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;
}
}
}
条件付き直列化値メンバーについては、XML Schema Binding Support: MinOccurs Attribute Binding SupportおよびShouldSerialize*() vs *Specified Conditional Serialization Patternを参照してください。
だから、主な違いですが、あなたが選択した影響を与える可能性だけでなく、二次違いがあります。
[XmlIgnore]
は、派生クラスでオーバーライドすることはできませんが、仮想としてマークされたときShouldSerializeXXX()
ができます。例についてはhereを参照してください。例えば、それはタイプを指す、ための部材をXmlSerializer
によってシリアライズすることができない場合
lacks a parameterless constructorこと、次いで含有タイプをシリアル化することを可能にする[XmlIgnore]
を有する部材をマーキング - 含有を許可しないShouldSerializeXXX() { return false; }
を加えながら前述のように、XmlSerializer
は静的型分析のみを実行するため、シリアライズされる型はシリアライズされます。例えば。次のようになります。
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; }
}
XmlSerializer
でシリアル化できません。
[XmlIgnore]
XmlSerializer
に特異的であるが、ShouldSerializeXXX()
はJson.NETとprotobuf-netを含む他のシリアライザによって使用されます。
Visual Studioで条件付きシリアル化プロパティの名前を変更しても、対応するShouldSerializeXXX()
メソッド名の名前が自動的に変更されることはありません。
すべてが標準に準拠している場合は、好みのものを選択してください。 PS ShouldSerializeXXXバージョンはひどいアイデアです、それを使わないでください! – DavidG
@DavidG:なぜShouldSerializeXXXを使うのはひどい考えですか? – scher
あなたはそれらの余分なすべてのメソッドであなたのモデルを汚染しますが、属性はそうしません。 – DavidG