Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize Enum from Xml using Value property in c#

I am trying to write an ONIX for book import tool in C#. I started by creating the classes using Xsd2Code and got a huge file with all the properties which after a few tweaks does not produce any error upon deserializing.

I am trying to deserialize an entire element in one go, into a big object in memory and then do stuff with it (such as save it to database).

The way the Xsd2Code generated the classes, apart from the fact that there are A LOT of properties, are a bit weird, at least to me.

Here's one of the classes which should be a property of the Product object:

public partial class NotificationType
{
    public NotificationTypeRefname refname { get; set; }
    public NotificationTypeShortname shortname { get; set; }

    public SourceTypeCode sourcetype { get; set; }

    public List1 Value { get; set; }
}

I would like to direct your attention to this line:

    public List1 Value { get; set; }

"List1" is an enum, defined like so:

public enum List1
{
    [System.Xml.Serialization.XmlEnum("01")]
    Item01,

    [System.Xml.Serialization.XmlEnum("02")]
    Item02, etc...

My problem is that during deserialization, all fields deserialize correctly EXCEPT the Enums.

I tried decorating the properties with XmlEnum("NotificationType") etc... nothing!

This is my deserialization code:

var p = new Product();
XmlSerializer pserializer = new XmlSerializer(p.GetType());
object pDeserialized = pserializer.Deserialize(reader);
p = (Product) pDeserialized;

This is how this element looks like in XML:

<NotificationType>03</NotificationType>

The property that is in C# for the Product object is:

public NotificationType NotificationType { get; set; }

If I change this to:

public List1 NotificationType { get; set; }

the deserialization correctly shows 'Item03', meaning it does read whatever is in XML. IF I leave it like above, the 'Value' property of the NotificationType class is never filled, and always shows Item01 (the default of the Enum).

I have exhausted all possible questions on SO and web searches as to WHY this Value property works with some types (Strings) but not Enums. Am I missing something?

Sorry for the long question and code. Appreciate any light anyone can shed on this issue. Been stuck with it for a whole day now.

like image 413
Cristian Cotovan Avatar asked Oct 21 '22 16:10

Cristian Cotovan


2 Answers

Try this:

public partial class NotificationType
{
    public NotificationTypeRefname refname { get; set; }
    public NotificationTypeShortname shortname { get; set; }
    public SourceTypeCode sourcetype { get; set; }

    public List1 Value { get {
        return (List1)Enum.Parse(typeof(List1), 
            Enum.GetName(typeof(List1), int.Parse(List1Value) - 1));
    }}

    [XmlText]
    public string List1Value { get; set; }
}

[UPDATE]

Since:

  1. I also tried at first decorating the member with the XmlText attribute, but the following exception was occurring:

    Cannot serialize object of type 'ConsoleApplication1.NotificationType'. Consider changing type of XmlText member 'ConsoleApplication1.NotificationType.Value' from ConsoleApplication1.List1 to string or string array.

  2. and you would like to avoid my initial approach in the answer,

the real solution is that, besides applying the XmlText attribute to Value, all the other members should be decorated with the XmlIgnoreAttribute. I believe that using XmlText alone is not a guaranteed solution, as the results depend on the existence of other members.

public class NotificationType
{
    [XmlIgnore] // required
    public NotificationTypeRefname refname { get; set; }
    [XmlIgnore] // required
    public NotificationTypeShortname shortname { get; set; }
    [XmlIgnore] // required
    public SourceTypeCode sourcetype { get; set; }

    [XmlText] // required
    public List1 Value { get; set; }
}
like image 64
Alex Filipovici Avatar answered Oct 27 '22 08:10

Alex Filipovici


Try adding [System.Xml.Serialization.XmlTextAttribute()] to the public List1 Value { get; set; } property.

like image 33
pbz Avatar answered Oct 27 '22 10:10

pbz