6

I'm trying to deserialize an XML string, where the value of an element, ain't within the scope of my Enum values.

Public enum MyEnum
{
    Unknown,
    Car,
    Bicycle,
    Boat
}

[SerializableAttribute()]
public class MyClass
{
    private string _id;
    private MyEnum _myEnum;

    public string ID
    {
        get { return _id; }
        set { _id = value; }
    }

    public MyEnum EnumValue
    {
        get { return _myEnum; }
        set { _myEnum = value; }
    }

    public MyClass(string id)
    {
        this._id = id;
    }

    public MyClass() : this("") { }
}

If I try to deserialize following string (note Plane as enum value):

<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><MyClass><ID>1234567890123456789</ID><EnumValue>Plane</EnumValue></MyClass>

then my deserialize will thrown an exception, before it even hit my public field for EnumValue, with following exception message:

Instance validation error: 'Plane' is not a valid value for EnumValue

Is it possible to return a default value for EnumValue, if the value I try to parse in the XML ain't supported as a EnumValue?? Eg. in the case of the XML string provided here, the EnumValue should be set as 'Unknown'.

grmihel
  • 784
  • 3
  • 15
  • 40

5 Answers5

6
[XmlIgnore]
public MyEnum EnumValueReal
{
    get { return _myEnum; }
    set { _myEnum = value; }
}

public string EnumValue
{
     get
     {
         return EnumValueReal.ToString();
     }

     set
     {
         MyEnum result = MyEnum.Unknown;
         Enum.TryParse(value, true, out result);

         EnumValueReal = result;
     }
}
SpiderCode
  • 10,062
  • 2
  • 22
  • 42
Yaugen Vlasau
  • 2,148
  • 1
  • 17
  • 38
  • EnumValue will be serialized and it allow to keep values that violate the MyEnum restriction. the same time the EnumValueReal can handle the constraint violation situation. Wasn't that the question that was asked? – Yaugen Vlasau Mar 07 '14 at 09:15
  • Sorry. my bad. I just saw XmlIgore mentioned in EnumValueReal. didn't look at EnumValue. Sorry again. (+1) – SpiderCode Mar 07 '14 at 09:20
  • 1
    Ended with this solution, but without creating a public MyEnum field with XmlIgnore tag on, since the private MyEnum myEnum in MyClass.cs won't be serialized anyways. Converting the Enum to a String, was the solution in my case. Thanks. – grmihel Mar 17 '14 at 13:04
1

Other way around would be to declare EnumValue as string and parse value in EnumValue property to MyEnum in another property (with custom logic). Another property should be marked as not serializable.

public string EnumValue
{
    get { return _myEnum; }
    set { _myEnum = value; }
}

[NonSerialized]
public MyEnum EnumValueTyped {
  get {
    MyEnum value;
    if (Enum.TryParse<MyEnum>(EnumValue, out value)) {
      return value;
    }
    return MyEnum.Unknown;
  }
  set {
    EnumValue = value.ToString();
  }
}
Ondrej Svejdar
  • 21,349
  • 5
  • 54
  • 89
1

Sometimes what happens is we do not take the update of the dlls or the projects we are referring in the project after making changes to the later and hence the parameter added/deleted does not get detected, thus throwing the same issue. Hence better take the updated dll and proceed.Can be a silly mistake but often committed. All the best :)

Nayan_07
  • 195
  • 1
  • 4
  • 13
1

IMHO the most 'appropriate' solution would be to make EnumValue property nullable - since error you are getting (and MyEnum.Unknown) implies that it is possible for this property not to have a value...

Code would look following:

public enum MyEnum
{
    Car,
    Bicycle,
    Boat
}

[Serializable()]
public class MyClass
{
    private string _id;
    private MyEnum? _myEnum;

    public string ID
    {
        get { return _id; }
        set { _id = value; }
    }

    public MyEnum? EnumValue
    {

        get { return _myEnum; }
        set { _myEnum = value; }
    }

    public MyClass(string id)
    {
        this._id = id;
    }

    public MyClass() : this("")
    {
    }
}
Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265
0

Yes, but you can't do it anymore with SerializableAttribute I think.

You should implement ISerializable and provide your own serializer/deserializer. You can use the default serializer (new BinaryFormatter().serializer() e.g), but you have to implement a custom deserialization.

C4stor
  • 8,355
  • 6
  • 29
  • 47