サードパーティからxmlを取得し、それをC#オブジェクトに逆シリアル化する必要があります。このxmlには、整数型または空の値の属性が含まれている場合があります:attr =” 11”またはattr =””。この属性値をnull許容整数型のプロパティに逆シリアル化したい。ただし、XmlSerializerはnull許容型への逆シリアル化をサポートしていません。次のテストコードは、InvalidOperationException{"タイプ'TestConsoleApplication.SerializeMe'を反映するエラーが発生しました。"}でXmlSerializerの作成中に失敗します。
[XmlRoot("root")]
public class SerializeMe
{
[XmlElement("element")]
public Element Element { get; set; }
}
public class Element
{
[XmlAttribute("attr")]
public int? Value { get; set; }
}
class Program {
static void Main(string[] args) {
string xml = "<root><element attr=''>valE</element></root>";
var deserializer = new XmlSerializer(typeof(SerializeMe));
Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(xml));
var result = (SerializeMe)deserializer.Deserialize(xmlStream);
}
}
'Value'プロパティのタイプをintに変更すると、逆シリアル化はInvalidOperationExceptionで失敗します。
XMLドキュメント(1、16)にエラーがあります。
空の値を持つ属性をnull許容型に(nullとして)逆シリアル化すると同時に、空でない属性値を整数に逆シリアル化する方法を誰かがアドバイスできますか?これには何かトリックがありますので、各フィールドの逆シリアル化を手動で行う必要はありません(実際には多くのフィールドがあります)?
ahsteeleからのコメント後に更新:
-
私の知る限り、この属性はXmlElementAttributeでのみ機能します。この属性は、子要素であろうと本文テキストであろうと、要素にコンテンツがないことを指定します。しかし、XmlAttributeAttributeの解決策を見つける必要があります。とにかく、私はそれを制御できないので、xmlを変更することはできません。
-
このプロパティは、属性値が空でない場合、または属性が欠落している場合にのみ機能します。attrの値が空の場合(attr ='')、XmlSerializerコンストラクターは失敗します(予想どおり)。
public class Element { [XmlAttribute("attr")] public int Value { get; set; } [XmlIgnore] public bool ValueSpecified; }
AlexScordellisによるこのブログ投稿のようなカスタムNullableクラス
私はこのブログ投稿から私の問題にクラスを採用しようとしました:
[XmlAttribute("attr")] public NullableInt Value { get; set; }
しかし、XmlSerializerコンストラクターはInvalidOperationExceptionで失敗します。
タイプTestConsoleApplication.NullableIntのメンバー'Value'をシリアル化できません。
XmlAttribute / XmlTextを使用して、IXmlSerializableを実装する型をエンコードすることはできません}
醜い代理ソリューション(私がこのコードをここに書いたことは恥ずべきことです:)):
public class Element { [XmlAttribute("attr")] public string SetValue { get; set; } public int? GetValue() { if ( string.IsNullOrEmpty(SetValue) || SetValue.Trim().Length <= 0 ) return null; int result; if (int.TryParse(SetValue, out result)) return result; return null; } }
しかし、このようなソリューションは、クラスのコンシューマーのインターフェイスを壊してしまうため、思いつきたくありません。IXmlSerializableインターフェースを手動で実装する方がよいでしょう。
現在、Elementクラス全体にIXmlSerializableを実装する必要があるようです(これは大きいです)。簡単な回避策はありません…</ p>