dahomey-technologies/Dahomey.Cbor

Cannot serialize enum in object member

pbleisch opened this issue · 1 comments

enum EnumThing 
{
  A,
  B
}

class X
{
  public EnumThing Action = EnumThing.A;
  public object Val = EnumThing.B;
}

[Fact]
async void CanRoundtripOp() 
{
  var op = new X();

  var options = new CborOptions() {
      DateTimeFormat = DateTimeFormat.Unix,
      UnhandledNameMode = UnhandledNameMode.Silent,
      EnumFormat = ValueFormat.WriteToInt,
      DiscriminatorPolicy = Dahomey.Cbor.Attributes.CborDiscriminatorPolicy.Always,
  };

  var stream = new MemoryStream();
  await Cbor.SerializeAsync(op, stream, options);  // throws exception
  
  stream.Position = 0;
  var op2 = await Cbor.DeserializeAsync<Op>(stream, options);
}
Exception has occurred: CLR/System.InvalidCastException
Exception thrown: 'System.InvalidCastException' in System.Private.CoreLib.dll: 'Unable to cast object of type 'Dahomey.Cbor.Serialization.Converters.EnumConverter`1[ObsTests.ObCborTests+EnumThing]' to type 'Dahomey.Cbor.Serialization.Converters.IObjectConverter'.'
   at System.Runtime.CompilerServices.CastHelpers.ChkCast_Helper(Void* toTypeHnd, Object obj)
   at Dahomey.Cbor.Serialization.Converters.ObjectConverter`1.Write(CborWriter& writer, T value, LengthMode lengthMode)
   at Dahomey.Cbor.Serialization.Converters.MemberConverter`2.Write(CborWriter& writer, Object obj)
   at Dahomey.Cbor.Serialization.Converters.ObjectConverter`1.WriteMapItem(CborWriter& writer, MapWriterContext& context)
   at Dahomey.Cbor.Serialization.CborWriter.WriteMap[TC](ICborMapWriter`1 mapWriter, TC& context)
   at Dahomey.Cbor.Serialization.Converters.ObjectConverter`1.Write(CborWriter& writer, T value, LengthMode lengthMode)
   at Dahomey.Cbor.Serialization.Converters.CborConverterBase`1.Write(CborWriter& writer, T value)
   at Dahomey.Cbor.Cbor.Serialize[T](T input, IBufferWriter`1& buffer, CborOptions options)
   at Dahomey.Cbor.Cbor.SerializeAsync[T](T input, Stream stream, CborOptions options, CancellationToken token)
   at ObsTests.ObCborTests.<CanRoundtripOp>d__7.MoveNext() in /Users/paul/proj/personal/mds/src/ObsTests/ObCborTests.cs:line 89

The exception seems to be because of the Val field. This appears to be due to the cast to IObjectConverter in ObjectConverter.Write because EnumConverter does not derive from ObjectConverter.

Is there a correct way to do this in Dahomey.Cbor? In my use case I cannot modify the class X and I would like to avoid hardcoding the list of valid types of Val.

Currently the library does not support automatic boxing a ValueType, including enums to an object property.

What you could do, is to write your own CborConverter to serialize manually all the different types supported by the Val property.
If you give me a little bit more details, I could help you.

For now, I'm going to close this issue, but feel free to open it again with more details