このオブジェクトがあるとしましょう:
[Serializable]
public class MyClass
{
public int Age { get; set; }
public int MyClassB { get; set; }
}
[Serializable]
public class MyClassB
{
public int RandomNumber { get; set; }
}
XmlSerializerは、次のようにオブジェクトをシリアル化します。
<MyClass>
<Age>0</age>
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
プロパティAgeをnullにできるようにするにはどうすればよいですか? IE:プロパティAgeが0未満のときにシリアル化しないようにするには?
私はNullableで試しましたが、それは私のように私のオブジェクトをシリアル化します:
<MyClass>
<Age d5p1:nil="true" />
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
MSDNのドキュメントを読むと、次のことがわかりました。
値型にはnullNothingnullptrnull参照(Visual BasicではNothing)を含めることができないため、IsNullableプロパティを値型として型指定されたメンバーに適用することはできません。さらに、null許容値型の場合、このプロパティをfalseに設定することはできません。このような型がnullNothingnullptrnull参照(Visual BasicではNothing)の場合、xsi:nilをtrueに設定することでシリアル化されます。
ソース: http://msdn.Microsoft.com/en-us/library/system.xml.serialization.xmlelementattribute.isnullable.aspx
値の型をnullに設定できないことを理解しています。 valuetypeは常に何かに設定されます。シリアル化では、現在の値に基づいてシリアル化するかどうかを決定できません。
私は属性で試しましたが、うまくいきませんでした。 agecontainerオブジェクトを作成して、属性を使用してシリアル化を操作しようとしましたが、うまくいきませんでした。
私が本当に欲しいのは:
<MyClass>
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
プロパティAgeが0(ゼロ)未満の場合。
カスタムのシリアル化を実装する必要があるようです。
ええ、私もそうですが、それなしで逃げたいです。
アプリケーションでは、オブジェクトははるかに複雑であり、シリアル化を自分で処理したくありません。
私はこれを発見しました。 XmlSerialier
はXXXSpecified
ブール型プロパティを探して、それを含めるかどうかを決定します。これは問題をうまく解決するはずです。
[Serializable]
public class MyClass
{
public int Age { get; set; }
[XmlIgnore]
public bool AgeSpecified { get { return Age >= 0; } }
public int MyClassB { get; set; }
}
[Serializable]
public class MyClassB
{
public int RandomNumber { get; set; }
}
証明:
static string Serialize<T>(T obj)
{
var serializer = new XmlSerializer(typeof(T));
var builder = new StringBuilder();
using (var writer = new StringWriter(builder))
{
serializer.Serialize(writer, obj);
return builder.ToString();
}
}
static void Main(string[] args)
{
var withoutAge = new MyClass() { Age = -1 };
var withAge = new MyClass() { Age = 20 };
Serialize(withoutAge); // = <MyClass><MyClassB>0</MyClassB></MyClass>
Serialize(withAge); // = <MyClass><Age>20</Age><MyClassB>0</MyClassB></MyClass>
}
編集:はい、それは文書化された機能です。 MSDNエントリXmlSerializer
を参照してください
別のオプションは、特別なパターンを使用して、XmlSerializerによって認識されるブール型フィールドを作成し、XmlIgnoreAttributeをフィールドに適用することです。パターンは、propertyNameSpecifiedの形式で作成されます。たとえば、「MyFirstName」という名前のフィールドがある場合、「MyFirstName」という名前のXML要素を生成するかどうかをXmlSerializerに指示する「MyFirstNameSpecified」という名前のフィールドも作成します。
Samuelの回答とGreg Beechのコメントをブールプロパティの場合に拡張します。プロパティがbool型の場合、propertySpecifiedプロパティで簡単なテストを作成することはできません。
解決策はNullable <bool>型を使用することであり、propertySpecifiedプロパティのテストは単にproperty.HasValueです。例えば.
using System.Xml.Serialization;
public class Person
{
public bool? Employed { get; set; }
[XmlIgnore]
public bool EmployedSpecified { get { return Employed.HasValue; } }
}
数値プロパティにnull許容型を使用する代わりに(Greg Beechが推奨)、次のようにvalueプロパティを-1などの無効なデフォルト値に設定します。
using System.ComponentModel;
using System.Xml.Serialization;
public class Person
{
[DefaultValue(-1)]
public int Age { get; set; }
[XmlIgnore]
public bool AgeSpecified { get { return Age >= 0; } }
}
XmlElementAttribute.IsNullableを使用できます。
[Serializable]
public class MyClass
{
[XmlElement(IsNullable = true)]
public int? Age { get; set; }
public int MyClassB { get; set; }
}
これはエイジをintにするのに役立ちますか?そして..
public bool ShouldSerializeAge() { return Age.HasValue; }
..それは、クラスにShouldSerializeXXXメソッドを追加することを意味します!
Nullableについて忘れてください... ShouldSerializeXXXはかなりの解決策です。ここで年齢はあなたの状態に基づいてシリアル化されます。
[Serializable]
public class MyClass
{
public int Age { get; set; }
public int MyClassB { get; set; }
#region Conditional Serialization
public bool ShouldSerializeAge() { return age > 0; }
#endregion
}
[Serializable]
public class MyClassB
{
public int RandomNumber { get; set; }
}
要素の「minoccurs」属性を「minoccurs = "0"」に設定した場合、xsd.exeはXXXSpecifiedプロパティとアクセサーを自動生成します。スキーマを使用してxml /クラスを定義している場合