Leonard
Leonard

Reputation: 3092

DataContractSerializer: can't deserialize because of changed property type

I have a property named Lender which previously was a string, and has since changed to the complex type Lender. I thought an implicit operator overload would resolve the transformation from a string to an object, but it doesn't, and deserialization fails.

Can I fix this in any way, or must I refactor my code for backwards compatibility?

Before:

class AnObject {
  string Lender { get; set; }
}

After:

class AnObject {
  Lender Lender { get; set; }
}

class Lender {
  public string Name { get; set; } // Previously the string property on AnObject.

  public static implicit operator Lender(string name) {
    return new Lender(name);
  }
}

Exception:

Error in line 1 position 249. Expecting state 'Element'.. Encountered 'Text' with name '', namespace ''.

Upvotes: 1

Views: 924

Answers (2)

Leonard
Leonard

Reputation: 3092

I had to "transition" the XML into the new format by replacing the text nodes under the Lender node with the Lender object serialized using the DataContract serializer.

Upvotes: 0

Mikko Viitala
Mikko Viitala

Reputation: 8404

You implemented implicit operator in wrong class, it should be in Lender.

public class AnObject
{
    public Lender Lender { get; set; }
}

public class Lender
{
    public Lender(string name)
    {
        Name = name;
    }

    public string Name { get; set; }

    public static implicit operator Lender(string name)
    {
        return new Lender(name);
    }

    public static implicit operator string (Lender lender)
    {
        return lender.Name;
    }
}

Then you can do

var obj = new AnObject();
obj.Lender = new Lender("lender");

and via implicit conversion

var obj = new AnObject();
obj.Lender = "lender";

Edit: Would the infamous dynamic do? Even if it works, it's scary.

public class Lender
{
    public Lender(string name)
    {
        Name = name;
    }

    public string Name { get; set; }
}

public class AnObject
{
    private Lender _lender;

    public dynamic Lender
    {
        get { return _lender; }
        set
        {
            _lender = value is string ? new Lender(value as string) : value as Lender;
        }
    }
}

Upvotes: 2

Related Questions