.NETのXmlSerializer
を操作するときに、非常に奇妙な問題があります。
以下のクラスの例をご覧ください。
public class Order
{
public PaymentCollection Payments { get; set; }
//everything else is serializable (including other collections of non-abstract types)
}
public class PaymentCollection : Collection<Payment>
{
}
public abstract class Payment
{
//abstract methods
}
public class BankPayment : Payment
{
//method implementations
}
私の知る限り、シリアライザが派生型InvalidOperationException
を知らないことに起因するPayment
を解決するための3つの異なる方法があります。
1。 XmlInclude
クラス定義へのPayment
の追加:
これは、私が制御できない外部参照としてすべてのクラスが含まれているため不可能です。
2。 XmlSerializer
インスタンスの作成中に派生型の型を渡す
動作しません。
3。ターゲットプロパティのXmlAttributeOverrides
を定義して、プロパティのデフォルトのシリアル化をオーバーライドする( this SO post )
また、動作しません(XmlAttributeOverrides
初期化が続きます)。
Type bankPayment = typeof(BankPayment);
XmlAttributes attributes = new XmlAttributes();
attributes.XmlElements.Add(new XmlElementAttribute(bankPayment.Name, bankPayment));
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
overrides.Add(typeof(Order), "Payments", attributes);
次に、適切なXmlSerializer
コンストラクターが使用されます。
注:は機能しませんInvalidOperationException
(BankPayment
は予期されていませんでした...)がスローされます。
誰もが主題にいくらか光を当てることができますか?どうすれば問題をさらにデバッグしてデバッグできますか?
問題を解決しました。しばらく掘り下げた後、 this SO post が見つかりました。これはまったく同じ状況をカバーしています。それは私を正しい軌道に乗せました。
基本的に、XmlSerializer
は、デフォルトの名前空間if派生クラスが追加の型として含まれていることを知る必要があります。これが発生しなければならない正確な理由はまだ不明ですが、それでもシリアル化は現在機能しています。
これは私のために働いた:
[XmlInclude(typeof(BankPayment))]
[Serializable]
public abstract class Payment { }
[Serializable]
public class BankPayment : Payment {}
[Serializable]
public class Payments : List<Payment>{}
XmlSerializer serializer = new XmlSerializer(typeof(Payments), new Type[]{typeof(Payment)});
this に基づいて、クラスを変更する代わりに使用していたXmlSerializer
のコンストラクターを変更することでこれを解決できました。
このようなものを使用する代わりに(他の回答で提案されています):
[XmlInclude(typeof(Derived))]
public class Base {}
public class Derived : Base {}
public void Serialize()
{
TextWriter writer = new StreamWriter(SchedulePath);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Derived>));
xmlSerializer.Serialize(writer, data);
writer.Close();
}
これは私がしました:
public class Base {}
public class Derived : Base {}
public void Serialize()
{
TextWriter writer = new StreamWriter(SchedulePath);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Derived>), new[] { typeof(Derived) });
xmlSerializer.Serialize(writer, data);
writer.Close();
}