2012-08-09 6 views
66

Ich habe ein sehr seltsames Problem, wenn ich mit .NET XmlSerializer arbeite.Verwenden Sie das XmlInclude- oder SoapInclude-Attribut, um Typen anzugeben, die nicht statisch bekannt sind

Nehmen Sie die folgende Beispiel Klassen:

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 
} 

AFAIK, gibt es drei verschiedene Methoden, um die InvalidOperationException zu lösen, die durch die Serializer nicht zu wissen, über die abgeleiteten Typen von Payment verursacht wird.

1. Hinzufügen XmlInclude zum Payment Klassendefinition:

Das ist nicht möglich aufgrund aller Klassen als externe Referenzen enthalten sind, über die ich keine Kontrolle haben.

2. Vorbei an den abgeleiteten Typen Typen bei der Erstellung der XmlSerializer Instanz

nicht funktioniert.

3. Definition XmlAttributeOverrides für die Zieleigenschaft, um der Unterkunft Standardserialisierung außer Kraft zu setzen (wie in this SO post erklärt)

auch nicht (XmlAttributeOverrides Initialisierung folgt) funktioniert.

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); 

Das entsprechende XmlSerializer Konstruktor dann verwendet werden würde.

HINWEIS: von funktioniert nicht Ich meine die InvalidOperationException (BankPayment war nicht zu erwarten ...) geworfen wird.

Kann jemand etwas Licht auf das Thema werfen? Wie würde man vorgehen und das Problem weiter debuggen?

Antwort

29

Nur das Problem gelöst. Nachdem ich noch eine Weile herumgegrubbelt hatte, fand ich this SO post, was genau die gleiche Situation abdeckt. Das hat mich auf den richtigen Weg gebracht.

Grundsätzlich muss der XmlSerializer den Standardnamespace kennen, wenn abgeleitete Klassen als zusätzliche Typen enthalten sind. Der genaue Grund dafür ist noch unbekannt, aber die Serialisierung funktioniert noch.

63

für mich Dies funktionierte:

[XmlInclude(typeof(BankPayment))] 
[Serializable] 
public Payment { }  

[Serializable] 
public class BankPayment : Payment {} 

[Serializable] 
public class Payments : List<Payment>{} 

XmlSerializer serializer = new XmlSerializer(typeof(Payments), new Type[]{typeof(Payment)}); 
+5

So ist der Basistyp alle seine Implementierungen wissen muss? Dies scheint keine sehr gute Lösung zu sein. Gibt es keinen anderen Weg? –

+1

@AlexanderStolz für die generische Implementierung übergeben neuen Typ beim Erstellen von XmlSerializable Object ist die beste Lösung. Wie erwähnt http://stackoverflow.com/a/2689660/698127 – Aamol

Verwandte Themen