c# serialize Gibt es einen Grund, warum eine mit XmlInclude dekorierte Basisklasse bei der Serialisierung noch eine Ausnahme vom Typ unbekannt auslöst?



xml deserialize example (1)

Das Problem, das Sie sehen, ist, dass die PaymentSummaryRequest den Namespace setzt. Sie können den Namespace entweder entfernen oder der PaymentSummary Klasse einen Namespace PaymentSummary :

[XmlRoot(Namespace = Constants.Namespace)]
[XmlInclude(typeof(xxxPaymentSummary))]
public abstract class PaymentSummary
{
}

Wie @Tedford in seinem Kommentar unter dem Namespace erwähnt, ist dies nur erforderlich, wenn abgeleitete Typen verwendet werden.

Beim Generieren der XML-Serialisierungsassembly sieht es so aus, als würde der Stammknoten keine Namespace-Gruppe haben und die Basisklasse nicht die XML-Include-Logik in der generierten Serialisierungsassembly enthalten.

Ein anderer Ansatz zur Lösung des Problems besteht darin, die Namespace-Deklarationen aus den Klassen selbst zu entfernen und den Namespace im XmlSerializer Konstruktor XmlSerializer :

var serializer = new XmlSerializer(
    typeof(PaymentSummaryRequest), 
    Constants.Namespace
);

Ich werde den Code vereinfachen, um Platz zu sparen, aber das, was dargestellt wird, veranschaulicht das Kernproblem.

Ich habe eine Klasse, die eine Eigenschaft hat, die ein Basistyp ist. Es gibt 3 abgeleitete Klassen, die dieser Eigenschaft zugewiesen werden können.

Wenn ich dem Container eine der abgeleiteten Klassen zuweise und versuche, den Container zu serialisieren, wirft der XmlSerializer das gefürchtete aus:

"Der Typ x wurde nicht erwartet. Verwenden Sie das Attribut XmlInclude oder SoapInclude, um Typen anzugeben, die statisch nicht bekannt sind."

Meine Basisklasse ist jedoch bereits mit diesem Attribut ausgestattet, daher muss es eine zusätzliche "versteckte" Anforderung geben.

Der wirklich seltsame Teil ist, dass der standardmäßige WCF-Serialisierer keine Probleme mit dieser Klassenhierarchie hat.

Die Containerklasse

[DataContract]
[XmlRoot(ElementName = "TRANSACTION", Namespace = Constants.Namespace)]
public class PaymentSummaryRequest : CommandRequest
{
    [DataMember]
    public PaymentSummary Summary { get; set; }

    public PaymentSummaryRequest()
    {
        Mechanism = CommandMechanism.PaymentSummary;
    }
}

Die Basisklasse

[DataContract]
[XmlInclude(typeof(xPaymentSummary))]
[XmlInclude(typeof(yPaymentSummary))]
[XmlInclude(typeof(zPaymentSummary))]
[KnownType(typeof(xPaymentSummary))]
[KnownType(typeof(yPaymentSummary))]
[KnownType(typeof(zPaymentSummary))]
public abstract class PaymentSummary
{     
}

Eine der abgeleiteten Klassen

[DataContract]
public class xPaymentSummary : PaymentSummary
{
}

Der Serialisierungscode

var serializer = new XmlSerializer(typeof(PaymentSummaryRequest));
serializer.Serialize(Console.Out,new PaymentSummaryRequest{Summary = new xPaymentSummary{}});

Die Ausnahme

System.InvalidOperationException: Beim Generieren des XML-Dokuments ist ein Fehler aufgetreten. ---> System.InvalidOperationException: Der Typ xPaymentSummary wurde nicht erwartet. Verwenden Sie das XmlInclude- oder SoapInclude-Attribut, um Typen anzugeben, die statisch nicht bekannt sind. beim

Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentSummaryRequest.Write13_PaymentSummary (String n, String ns, PaymentSummary o, Boolean isNullable, Boolean needType) um

Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentSummaryRequest.Write14_PaymentSummaryRequest (String n, String ns, PaymentSummaryRequest o, Boolean isNullable, Boolean needType) um

Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentSummaryRequest.Write15_TRANSACTION (Object o) --- Ende der inneren Trace-Ablaufverfolgung für Ausnahmebedingungen --- um

System.Xml.Serialization.XmlSerializer.Serialize (XmlWriter xmlWriter, Object o, XmlSerializerNamespaces-Namespaces, String codingStyle, String-ID) um

System.Xml.Serialization.XmlSerializer.Serialize (TextWriter textWriter, Object o, XmlSerializerNamespaces-Namespaces)
bei UserQuery.RunUserAuthoredQuery () in c: \ Users \ Tedford \ AppData \ Local \ Temp \ uqacncyo.0.cs: Zeile 47