aaubry / YamlDotNet

YamlDotNet is a .NET library for YAML
MIT License
2.48k stars 466 forks source link

15.1.0 EnsureRoundTrip no longer works without tag mapping and protected default constructors #901

Closed tim-rue closed 5 months ago

tim-rue commented 5 months ago

Describe the bug When trying out the new release I encountered two problems with my project.

  1. EnsureRoundtrip() does not work if I use a tag mapping for each class, but it worked before. Why do I need a tag mapping if the type can be resolved through the object graph?
  2. EnablePrivateConstructors() used to enable protected constructors as well. Now I have to use private or public constructors

To Reproduce

public void SerializeTestClass()
{
    var testClass = new TestClass("test");
    var serializer = new SerializerBuilder()
        .EnablePrivateConstructors()
        .IncludeNonPublicProperties()
        .EnsureRoundtrip()
        .Build();

    var deserializer = new DeserializerBuilder()
        .EnablePrivateConstructors()
        .IncludeNonPublicProperties()
        .WithNamingConvention(PascalCaseNamingConvention.Instance)
        .Build();

    var stringWriter = new StringWriter();
    serializer.Serialize(stringWriter, testClass);
  }

 public class TestClass
 {
    public TestClass()
    {
        // protected constructor
    }

    public TestClass(string value)
    {
        Value = value;
    }

    public string Value { get; private set; }
}

This works in 13.7.1, but not in 15.1.0:

Cannot serialize type 'TestClass' where a 'System.Object' was expected because no tag mapping has been registered for TestClass', which means that it won't be possible to deserialize the document.

.WithTagMapping(new TagName("!Test"), typeof(TestClass)) does fix the problem, but that doesn't help for existing yaml files.

These are very breaking changes and make backwards compability impossible. For each class I serialize, I'd have to add a type mapping and make the constructor private instead of protected. Is there any solution I don't know about?

EdwardCooke commented 5 months ago

I'll take a look at them now. These shouldn't have been affected at all. While I look into this, can you send me an example of the yaml your using?

EdwardCooke commented 5 months ago

Ok, found the issues. There was 2 problems, one with internal constructors. That will be fixed. The other is with the ensureroundtrip. There was an option that was supposed to be set so it would do something, but, it was never set in the typeassigningeventemitter. That was now correctly being set which is why you are seeing the behavior. Since that is different from what was expected I've removed the relevant code so that is back to how it was.

I've also adjusted the tests to include the 4 different types of constructors, internal, private, protected and public.

I'll get a new version out today hopefuly.

aaubry commented 5 months ago

A fix for this issue has been released in version 15.1.1.

tim-rue commented 5 months ago

All our tests are passing now and the behavior seems to be back to how it was. Thanks a lot!