How do I resolve this enum cast issue when using ImpromptuInterface?

1k views Asked by At

Given the following code:

public enum Pet
{
    Cat,
    Dog
}

public interface IOwner
{
    Pet Pet
    {
        get;
        set;
    }
}

public class Owner : IOwner
{
    public Pet Pet
    {
        get;
        set;
    }
}

The following tests fail:

[TestFixture]
public class ImpromptuInterfaceExample
{
    private Owner owner;
    private ExpandoObject dynamicOwner;

    [SetUp]
    public void SetUp()
    {
        owner = new Owner { Pet = Pet.Dog };
        string serializedOwner = JsonConvert.SerializeObject(owner);
        dynamicOwner = JsonConvert.DeserializeObject<ExpandoObject>(serializedOwner);
    }

    [Test]
    public void InvalidCastException()
    {
        var duckType = ImpromptuDictionary.Create<IOwner>(dynamicOwner);
        Assert.That(duckType.Pet, Is.EqualTo(owner.Pet)); // System.InvalidCastException : Invalid cast from 'System.Int64' to 'JsonSerializationDemo.Pet'.
    }

    [Test]
    public void RuntimeBinderException()
    {
        var duckType = dynamicOwner.ActLike<IOwner>();
        Assert.That(duckType.Pet, Is.EqualTo(owner.Pet)); // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : Cannot implicitly convert type 'long' to 'JsonSerializationDemo.Pet'. An explicit conversion exists (are you missing a cast?)
    }
}

Is there a way to properly resolve this problem?

2

There are 2 answers

3
jbtule On BEST ANSWER

Your line:

 var duckType = ImpromptuDictionary.Create<IOwner>(dynamicOwner);

Should have worked but there was a bug with Enums specifically in ImpromptuInterface that is now fixed in version 6.0. ImpromptuDictionary tries several ways to coerce a type at runtime and was using the wrong one for Enums. So it works now.

1
Euphoric On

I think, the problem stems from fact, that Json serialiser serialises enums as numbers. But when it deserialises it into expando object, then it cannot possibly know, that the property is actualy an enum. This results in integer value in expando object.

This then confuses the impromptu-interface and causes exception in casting proxy. I think this could be resolved here, that the proxy builder would check, if the target type is enum, and use working coversion of in into enum. But you should take it to official page. I don't think SO can solve this problem.