Azure / autorest.csharp

Extension for AutoRest (https://github.com/Azure/autorest) that generates C# code
MIT License
143 stars 166 forks source link

Multi-level discriminated models don't set their discriminators correctly #5156

Open trrwilson opened 2 weeks ago

trrwilson commented 2 weeks ago

Problem summary

When defining a discriminated type that extends another discriminated type, the generated constructors for the downstream types don't set the right values, which results in malformed serialization.

Repro

Standalone project: csharp-emitter-double-discriminator-repro.zip

Example models (from main.tsp):

@discriminator("taxonomic_family")
model Animal {
  taxonomic_family: string;
}

@discriminator("breed")
model Dog extends Animal {
  taxonomic_family: "canidae";
  breed: string;
}

model Labrador extends Dog {
  breed: "labrador";
}

With the above, the public Dog() constructor is an instance of the issue.

More details

From the README included in the above repro .zip:

npm install @azure-tools/typespec-csharp @autorest/csharp --save-dev
npx tsp compile .

Search for and open Dog.cs and observe the generated constructors:

        /// <summary> Initializes a new instance of <see cref="Dog"/>. </summary>
        public Dog()
        {
            Breed = "canidae";
        }

        /// <summary> Initializes a new instance of <see cref="Dog"/>. </summary>
        /// <param name="taxonomicFamily"></param>
        /// <param name="serializedAdditionalRawData"> Keeps track of any properties unknown to the library. </param>
        /// <param name="breed"></param>
        internal Dog(string taxonomicFamily, IDictionary<string, BinaryData> serializedAdditionalRawData, string breed) : base(taxonomicFamily, serializedAdditionalRawData)
        {
            Breed = breed;
        }

While the internal constructor is correct and properly sets the inner discriminator of Breed to the provided value while invoking the parent type's base constructor to set the outer discriminator of taxonomic_family, the public constructor has multiple issues:

As a result of this, serialized instances of Dog are very malformed:

{
  "taxonomic_family": null,
  "breed": "canidae"
}
ArcturusZhang commented 2 weeks ago

@trrwilson :( unfortunately this is known issue for quite a long time. Here is another issue tracking this: https://github.com/Azure/autorest.csharp/issues/5146

@JoshLove-msft do you know how and when we could deal with this? As far as I know, the new generator should be able to handle this case, right?

JoshLove-msft commented 2 weeks ago

Yes, the new generator has support for multi-level discriminators.