Ceras: Bug: Serialization of readonly nullable custom struct fails
Trying to serialize a class containing a readonly field of a custom struct type throws an exception: ‘The binary operator Equal is not defined for the types ‘System.Nullable`1[A.Test]’ and ‘System.Nullable`1[A.Test]’.’
Config:
var config = new SerializerConfig { DefaultTargets = TargetMember.AllFields, PreserveReferences = false };
config.Advanced.ReadonlyFieldHandling = ReadonlyFieldHandling.ForcedOverwrite;
config.Advanced.SkipCompilerGeneratedFields = false;
config.OnConfigNewType = tc => tc.TypeConstruction = TypeConstruction.ByUninitialized();
Types:
public class Wrapper
{
public readonly Test? NullableStruct;
public Wrapper(Test? nullableStruct)
{
NullableStruct = nullableStruct;
}
}
public struct Test
{
public decimal Value;
}
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 18 (9 by maintainers)
Commits related to this issue
- more progress on #64 — committed to rikimaru0345/Ceras by rikimaru0345 5 years ago
- custom struct equality checks almost done (#64) — committed to rikimaru0345/Ceras by rikimaru0345 5 years ago
Correct me if I’m wrong, but I think this thread is missing the root cause of the exception: System.ArgumentException: ‘Expression of type ‘A.CustomProperty’ cannot be used for parameter of type ‘System.Object’ of method ‘Void SetValue(System.Object, System.Object)’ (Parameter ‘arg0’)’
The problem is that the method SetValue is being passed a first parameter (the target of the SetValue call) of type ref T where T : struct, but SetValue expects a parameter of type System.Object. In EmitReadonlyWriteBack, the expression tree passes refValueArg directly to the Expression.Call, resulting in a failed cast from ref struct to object. The solution is to box the struct, then call SetValue, and finally unbox the struct and assign it back to the value parameter.
This boxing and unboxing is obviously best avoided (the equality check helps with this), but it’s necessary to be able to use SetValue properly on a struct.