1

クラスの 1 つで IXMLSerializable を実装しています。null 許容の数値プロパティがいくつか含まれています (int? double? など)。

IXMLSerializable を介してこれらをシリアル化/シリアル化する正しい方法は何ですか? これが私が今していることです。これは機能しますが、明らかに正しい方法ではないようです。

void IXmlSerializable.WriteXml(XmlWriter writer)
{
    ...

    if (this._PropName == null)
    {
        writer.WriteElementString("PropName", "NULL");
    }
    else
    {
        writer.WriteElementString("PropName", this._PropName.ToString());
    }
    ...
}

void IXmlSerializable.ReadXml(XmlReader reader)    
{
    string tempStr;
    ...

    reader.ReadStartElement("PropName"); 

    if (tempStr != "NULL")
    {
        this._PropName = double.Parse(tempStr);
    }
    else 
    {
        this._PropName = null;
    }
    ...
}

更新: IXmlSerializable を実装している理由について、少し背景を説明するように求められました。私は床のコレクションを表すクラスが必要な建築設計のプログラムに取り組んでいます。各フロアには、 Floor.Areaエリア、Floor.Heightなどのプロパティがあります。ただし、フロアの高さは、その下のフロアの高さの合計によって定義されます。したがって、Floor.Heightプロパティが変更されるか、FloorCollectionが変更されるたびに、フロアの高さが再計算されます。

シリアル化する必要がある FloorCollectionクラスは、BindingList から継承しています。このクラスを直接シリアル化しようとすると、フロアのコレクションがシリアル化されますが、クラスのプロパティやフィールドはシリアル化されません。これに関する私の以前の投稿を参照してください。

現在、コレクション内の建物の床の最大高さ、最大上部高さ、および最小下部高さを制限する機能を追加しようとしています。したがって、これらの制限を表すために nullable double を使用しています。null 値は無制限を意味します。標高プロパティは、正、負、またはゼロにすることができます。そのため、制限がない場合を識別する別の状態 null が必要です。

標高/高さの制限があるかどうかを識別する別のブール値と、それが有効な場合に制限が何であるかを識別する通常の double プロパティを持つ方が全体的に簡単かもしれないと考えています。

4

4 に答える 4

3

null の場合は要素を省略します。

編集

プロパティを追加した新しいバージョンを作成するとどうなるかを考えてみてください。その後、古いバージョンのコピーを逆シリアル化すると、新しいプロパティを含む新しい要素が失われるため、プロパティを初期化せずに null として正しく残すことができます。これは同じ論理であり、現在時制をカバーするように拡張されています。

編集

カスタム シリアライザーを記述せずに XmlSerializer に null プロパティを省略するように指示する方法については、このを確認してください。また、背景情報を考えると、私はまだ xsi:nil の省略を好みますが、後者が許容できる解決策であると考えています。

于 2009-08-18T02:22:38.927 に答える
3

プロパティの XML を常に記述したいが、プロパティ値が null の場合は xsi:nil="true" 属性を含めたい。

void IXmlSerializable.WriteXml(XmlWriter writer)
{
    ...

    if (this._PropName == null)
    {
        writer.WriteStartElement("PropName");
        writer.WriteAttributeString("xsi", "nil", "http://www.w3.org/2001/XMLSchema-instance", "true");
        writer.WriteEndElement();
    }
    else
    {
        writer.WriteElementString("PropName", this._PropName.ToString());
    }
    ...
}

また、おそらく xsi:type="xsd: datatype " 属性を書きたいと思うでしょう。ここで、xsd はhttp://www.w3.org/2001/XMLSchema名前空間です。これにより、逆シリアル化中にデータ型を読み込んで、値を変換するかどうか (およびその方法) を知ることができます。

于 2009-08-18T02:46:39.670 に答える
1

null を書くことができます:

writer.WriteElementString("Test", null);

次のような要素になります<Test/>

または、 xsi:nil属性を使用して null 値をもう少し具体的にすることができます。

const string xsiNs = "http://www.w3.org/2001/XMLSchema-instance";
using (XmlWriter writer = XmlWriter.Create(Console.Out))
{
  writer.WriteStartElement("Test");
  writer.WriteAttributeString("xsi", "nil", xsiNs, "true");
  writer.WriteEndElement();
}

その結果、<Test xsi:nil="true"/>

于 2009-08-18T02:38:14.583 に答える
0
void IXmlSerializable.WriteXml(XmlWriter writer)
{
  if (this._Foo == null)
  {
    writer.WriteStartElement("Foo");
    writer.WriteEndElement("Foo");
  }
  else
  {
    writer.WriteElementString("Foo", this._Foo.ToString());
  }
}
于 2009-08-18T02:28:31.057 に答える