カスタムXMLシリアル化でのみシリアル化できるクラスがあります。これは、使用するはるかに大きなシステム内の特定のクラスのプロパティとして使用されます基本的なシリアル化。私はシステム全体をカスタムシリアル化に変換することはできません。巨大で、将来的には基本的なシリアル化を使用するサードパーティのモジュールが含まれている可能性があるからです。Listがカスタムシリアル化を使用する複数のオブジェクトを参照すると、基本的なXMLシリアル化が失敗する
私の最初の質問は、これがまったく許されるかどうかです。私はMSDNで、あなたが基本シリアル化されたものからカスタムシリアル化されたオブジェクトを参照することを許可されていないと言うことはできませんし、そうでない場合にはコードの移植性に重大な制限があるように見えます。しかし、このサイトの初期の答えは、あなたができないかもしれないことを示唆しているようです(このポスターは「あなたが実際に直列化を混ぜ合わせて一致させることはできません、一度IXmlSerializableを実装すれば、クラス内でのミキシングとマッチングを行うことができます。実際にはこれが許されていると仮定すると、メインシステム内のクラスがカスタムシリアル化を持つクラスの2つ以上のオブジェクトを含むリストを実装するときは常に失敗するということです。
興味深いことに、エラーはデシリアライズ時にのみ発生し、そのようなオブジェクトへの参照が複数存在する場合にのみ発生します。さらに興味深いのは、リストが依存関係のチェーンの上に表示されても、同じ方法で失敗します(たとえば、リストには通常のオブジェクトが含まれています(通常のオブジェクトが含まれます。
私は、以下のように最も単純なケースを示す小さなテストプログラムを書いています。
だから私の質問は以下のとおりです。
- は、それが実際に 基本シリアル化されたものから、カスタムシリアル化されたオブジェクトを参照することができますか?
- もしそうなら、私は何か愚かなことをしていますか?
- これが既知のバグですか?テストプログラムON
NOTES: データクラス構造が非常に簡単であり、(基本的なシリアライゼーションを使用)クラスBasicXml及び(カスタムシリアル化を使用して)クラスCustomXmlから成ります。 BasicXmlには、CustomXmlのリストが含まれています。 もう一方のクラスには自己テストのテストが含まれています。インスタンス化してRunTests()を実行するだけです。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace AdHocTests
{
[Serializable]
public class BasicXml
{
public List<CustomXml> TestList { get; set; }
}
[Serializable]
public class CustomXml : IXmlSerializable
{
public CustomXml() { }
public CustomXml(string name)
{
Name = name;
}
public string Name { get; set; }
public void ReadXml(XmlReader reader)
{
Name = reader.ReadString();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteString(Name);
}
public XmlSchema GetSchema()
{
return null; // I have removed this code for clarity
}
}
public class MixedSerializationTest
{
public MixedSerializationTest()
{
_serializer.UnknownElement += UnknownElementHandler;
}
public void RunTests()
{
RunOneTest(makeItFail: false);
RunOneTest(makeItFail: true);
}
private void RunOneTest(bool makeItFail)
{
Debug.Write("\n\nRUNNING TEST THAT WILL " + (makeItFail ? "FAIL" : "PASS") + ":\n\n");
CustomXml c1 = new CustomXml("Hello");
CustomXml c2 = new CustomXml("World");
BasicXml b1 = new BasicXml
{
TestList = makeItFail ? new List<CustomXml> { c1, c2 } : new List<CustomXml> { c1 }
};
XElement xml1 = GetXmlFromObject(b1);
Debug.Write("Serialized XML:\n" + xml1.ToString() + "\n=====\n");
BasicXml b2 = GetObjectFromXml(xml1);
if (_cancelDeserialization) return;
XElement xml2 = GetXmlFromObject(b2);
Debug.Write("Reserialized XML:\n" + xml2.ToString() + "\n=====\n");
}
private XElement GetXmlFromObject(BasicXml obj)
{
using (StringWriter sw = new StringWriter())
{
using (XmlWriter xw = XmlWriter.Create(sw))
{
_serializer.Serialize(xw, obj);
return XElement.Parse(sw.ToString());
}
}
}
private BasicXml GetObjectFromXml(XElement xml)
{
using (StringReader sr = new StringReader(xml.ToString()))
{
XmlWriterSettings settings = new XmlWriterSettings();
using (XmlReader xr = XmlReader.Create(sr))
{
return (BasicXml)_serializer.Deserialize(xr);
}
}
}
private void UnknownElementHandler(object sender, XmlElementEventArgs e)
{
Debug.Write("\n*** Serializer threw an UnknownElement exception ***\n\n");
_cancelDeserialization = true;
}
private XmlSerializer _serializer = new XmlSerializer(typeof(BasicXml));
private bool _cancelDeserialization = false;
}
}
CustomXmlが* IXmlSerializableを実装していない場合は動作しますが、これはいくつか不足していることを示しています。 – RamblinRose
ニース[mcve]!私はすぐに問題を再現することができました。 – dbc
こんにちはRamblinRose、よくIXmlSerializableインターフェイスを削除するのは、カスタムではなく基本的なシリアル化に戻すスイッチなので、通常の基本+基本的な状況に戻っています。そして、インターフェイスが(基本的な+カスタムの状況を示す)定位置にあるとき、それはほぼ常に動作し、常に完全にシリアライズされます。これは、コードが正しいかもしれないことを示唆しています。私が描いた非常に特殊な状況の下では、この奇妙なことをするのです。 – Geoffff