Skip to content

[http-client-csharp] Add discriminated union extends support - #12481

Open
Jorge Rangel (jorgerangel-msft) wants to merge 14 commits into
microsoft:mainfrom
jorgerangel-msft:jorgerangel-msft-union-extends-support
Open

Jorge Rangel (jorgerangel-msft) wants to merge 14 commits into
microsoft:mainfrom
jorgerangel-msft:jorgerangel-msft-union-extends-support

Conversation

@jorgerangel-msft

Copy link
Copy Markdown
Contributor

Summary

  • Support tagged JSON @discriminated unions with an explicit model base and nominally inherited model variants, exposing the declared base in generated C# APIs.
  • Adopt TCGC's inline-discriminator projection and add context-specific object-envelope serialization, including custom discriminator/payload names, nullable values, arrays, and dictionaries. Direct uses of payload models remain unwrapped.
  • Forward discriminator values through untagged intermediate models while preserving existing rebased-discriminator constructor behavior.
  • Add one Sample-TypeSpec hierarchy, positive/negative unit tests, serialization baselines, and Spector coverage for explicit, injected, custom, enum, and recursive inline discriminators.

Scope and dependencies

This covers the tagged JSON section of the .NET design. @events/SSE support is not included. Unions that do not meet the supported explicit-base and nominal-inheritance requirements retain their existing representation.

Uses the compatible prereleases containing the required metadata/projection: TCGC 0.74.0-dev.9 and Azure Core 0.74.0-dev.4. HTTP spec dependencies are updated to include the integration scenarios.

Validation

  • npm run build and generated Sample-TypeSpec compilation passed.
  • Emitter tests: 422 passed, 2 skipped.
  • Input serialization tests: 318 passed.
  • Focused generator/model-factory tests: 658 passed.
  • Focused client-model serialization/method tests: 876 passed.
  • Generated sample runtime tests: 18 passed.
  • Spector: all 5 tests passed, covering 18 wire contracts.
  • Repository-root formatting, scoped Oxlint, and Cop checks passed.

Validation after the constructor compatibility fix used the scoped suites above; a second full .NET test run was not performed.

Relates to #12478.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp label Nov 3, 2026
Join-Path 'http' 'type' 'file'
Join-Path 'http' 'client' 'naming' # pending until https://github.com/microsoft/typespec/issues/5653 is resolved
Join-Path 'http' 'type' 'union' 'discriminated' # pending design
Join-Path 'http' 'type' 'union' 'discriminated' # Unconstrained unions; the extends subdirectory is supported.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undo this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored the original skip-list comment in bc8dff2.

--generated by Copilot

$command += " --emit $emitterDir"
$configFile = Join-Path $generationDir "tspconfig.yaml"
if (Test-Path $configFile) {
if ((Test-Path $configFile) -and (Split-Path $specFile) -ne $generationDir) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Sample-TypeSpec config uses kind: project. Passing it explicitly through --config produces config-project-not-as-cli-config: "--config cannot point to a project config (with kind: project)." When the spec and config are colocated, omitting --config lets the compiler discover the project config normally. The guard preserves the explicit config argument when the spec is elsewhere, so those generation paths still use the intended config.

--generated by Copilot


using Azure.ClientGenerator.Core;

@@clientName(Type.Union.Discriminated.Extends.ExplicitDiscriminator.PetBase, "ExplicitPet");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we have to rename these models ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The five scenarios each define PetBase, Cat, and Dog in separate TypeSpec namespaces, but the generator writes model files to flat src/Generated/Models/{Name}.cs paths. I regenerated without the renames: the code model retained the five namespace-qualified models, but the generated files overwrote one another. These client-side renames keep each scenario's models distinct without changing the shared Spector specs or expanding this PR into a generated-file layout change.

--generated by Copilot

namespace SampleTypeSpec
{
/// <summary> The UnionPet. </summary>
public partial class UnionPet

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be generated as an abstract type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed union base models to generate as abstract in bc8dff2. The generated constructors and model factory follow the abstract-model pattern, and direct non-null base deserialization throws rather than trying to instantiate the abstract type. Added generator and runtime coverage, including a base shared by multiple unions.

--generated by Copilot

/// <param name="writer"></param>
/// <param name="value"></param>
/// <param name="options"></param>
internal static void Serialize(Utf8JsonWriter writer, UnionPet value, ModelReaderWriterOptions options)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we not just generate this Serialize method within the model's existing serialization file instead as an internal static method?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved serialization into an internal static method on the base model's existing .Serialization.cs partial in bc8dff2, and removed the separate generated helper type. The method name includes the union name because multiple unions can share the same base while using different discriminator and envelope formats. Added shared-base coverage and handling for same-named unions in different namespaces.

--generated by Copilot


/// <param name="element"></param>
/// <param name="options"></param>
internal static UnionPet Deserialize(JsonElement element, ModelReaderWriterOptions options)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, can we just add this as an internal static method in the generated serialization file instead of creating a new type ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved deserialization into an internal static method on the base model's existing .Serialization.cs partial as well. Call sites now select the union-specific method rather than a separate helper type. Added round-trip coverage for two unions sharing the same base with different tags, discriminator names, and envelope names, so their wire formats stay separate.

--generated by Copilot

Make envelope union bases abstract and emit context-specific union methods in their model serialization files. Cover shared-base wire formats and restore the Spector skip comment.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft

JoshLove-msft commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Resolved the conflicts with main and pushed merge commit 6ab759d. The union changes are retained alongside the upstream lifecycle revert and the migration to TCGC's @dynamicModel decorator.

The dependency blocker is resolved for this branch by pinning compiler 1.18.0-dev.14, TCGC 0.74.0-dev.16, and Azure Core 0.74.0-dev.5. A compiler-only npm override keeps dependencies on that same compiler despite their stale stable-only peer ranges; no --force or --legacy-peer-deps installation flags are needed. Regenerated the client fixtures with the merged implementation.

All six original inline review comments have replies.

--generated by Copilot

Preserve union serialization while adopting the upstream lifecycle revert and dynamic-model decorator migration. Align prerelease compiler and TCGC dependencies, override stale compiler peer constraints, and regenerate client fixtures.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@pkg-pr-new

pkg-pr-new Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@12481

commit: 7fa9878

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

…eneration

Keep the union-extends Spector client non-stubbed under the default generation command so CI regeneration matches the committed runtime-test fixture. Preserve stub generation for other Spector scenarios.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft

Copy link
Copy Markdown
Contributor

Fixed the regeneration failures in e303b24. The default generation command was replacing the executable union-extends Spector client with API-only stubs, which caused the generated-file drift on both platforms. That scenario now retains its executable client during default regeneration; other scenarios still generate stubs.

Verified default regeneration leaves both the union-extends fixture and an unrelated stub fixture unchanged, and the five union Spector scenarios still pass.

--generated by Copilot

Generate and commit the missing union-extends debugger profile using ScmCodeModelGenerator, matching the executable Spector fixture and eliminating remaining CI regeneration drift.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft

Copy link
Copy Markdown
Contributor

Fixed the remaining regeneration drift in 2ad40bb. The latest run confirms the generated clients now match; the only outstanding difference was the missing union-extends debugger launch profile. Added that generated profile and made it select ScmCodeModelGenerator, matching the executable fixture. Repeated launch-profile generation produces identical output.

--generated by Copilot

@JoshLove-msft
JoshLove-msft marked this pull request as ready for review November 5, 2026 20:08
Copilot AI balanced review requested due to automatic review settings November 5, 2026 20:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Union handling generates uncompilable SDK code for BinaryData customizations and leaves supported envelope variants internal, preventing consumers from constructing them or accessing variant-specific properties.

2 open issues
1 file not reviewed
  • packages/http-client-csharp/package-lock.json: Generated file
What changed in this PR

Adds C# support for tagged JSON unions with an explicit model base and nominally inherited variants, addressing #12478. The implementation preserves union-specific envelopes while keeping direct payload-model serialization unwrapped.

Changes:

  • Updates dependencies and carries supported union metadata from the emitter into the generator.
  • Adds contextual envelope serialization and inherited-discriminator constructor handling.
  • Adds sample hierarchies, serialization baselines, Spector coverage, and generation-script integration.
File Description
packages/​http-client-csharp/​package.json Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​Type.Union.Discriminated.Extends.slnx Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​Type.Union.Discriminated.Extends.NuGet.targets Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​tests/​Type.Union.Discriminated.Extends.Tests.csproj Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Type.Union.Discriminated.Extends.csproj Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​schema/​ConfigurationSchema.json Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Recursive.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownRecursivePet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownInjectedPet.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownInjectedPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownExplicitPet.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownExplicitPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownEnumPet.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownEnumPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownCustomPet.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​UnknownCustomPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​RecursivePet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​RecursiveDog.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​RecursiveCat.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​PetKind.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​PetKind.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​Mammal.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​Mammal.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​InjectedPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​InjectedDog.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​InjectedDog.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​InjectedCat.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​ExplicitPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​ExplicitDog.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​ExplicitDog.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​ExplicitCat.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​ExplicitCat.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​EnumPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​EnumDog.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​EnumDog.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​EnumCat.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​EnumCat.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​CustomPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​CustomDog.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​CustomDog.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​CustomCat.Serialization.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​CustomCat.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Models/​_TypeUnionDiscriminatedExtendsContext.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​Utf8JsonBinaryContent.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​SerializationFormat.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​PipelineRequestHeadersExtensions.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​Optional.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​ErrorResult.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​CodeGenTypeAttribute.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​CodeGenSuppressAttribute.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​CodeGenSerializationAttribute.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​CodeGenMemberAttribute.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​ClientPipelineExtensions.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​ChangeTrackingList.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​ChangeTrackingDictionary.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​CancellationTokenExtensions.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​BinaryContentHelper.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​Internal/​Argument.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​InjectedDiscriminatorOperations.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​InjectedDiscriminator.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​InjectedDiscriminator.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​ExtendsClientSettings.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​ExtendsClientOptions.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​ExtendsClient.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​ExtendsClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​ExplicitDiscriminatorOperations.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​ExplicitDiscriminator.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​ExplicitDiscriminator.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​EnumDiscriminatorOperations.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​EnumDiscriminator.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​EnumDiscriminator.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​CustomDiscriminatorOperations.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​CustomDiscriminator.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​src/​Generated/​CustomDiscriminator.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​Configuration.json Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​type/​union/​discriminated/​extends/​client.tsp Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector/​http/​azure/​client-generator-core/​response-replacement/​tspCodeModel.json Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector.Tests/​TestProjects.Spector.Tests.csproj Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Spector.Tests/​Http/​_Type/​Union/​Discriminated/​Extends/​UnionExtendsTests.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​tspconfig.yaml Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​UnionExtends.RestClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​SampleTypeSpecModelFactory.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​SampleTypeSpecClient.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​UnionPetContainer.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​UnionPet.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​UnionDog.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​UnionCat.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​src/​Generated/​Models/​SampleTypeSpecContext.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​TestProjects/​Local/​Sample-TypeSpec/​Sample-TypeSpec.tsp Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​TypeFactory.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Providers/​ModelProvider.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Properties/​launchSettings.json Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator/​src/​Primitives/​PropertyWireInformation.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.Input/​src/​InputTypes/​Serialization/​InputUnionTypeConverter.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.Input/​src/​InputTypes/​Serialization/​InputNamespaceConverter.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.Input/​src/​InputTypes/​InputUnionType.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.Input/​src/​InputTypes/​InputNamespace.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​test/​Providers/​TestData/​DiscriminatedUnionSerializationTests/​WritesContextualEnvelopeSerialization(type,data).cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​test/​Providers/​TestData/​DiscriminatedUnionSerializationTests/​WritesContextualEnvelopeSerialization(kind,value).cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​test/​Providers/​MrwSerializationTypeDefinitions/​DiscriminatorTests.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​src/​Providers/​ScmModelProvider.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​src/​Providers/​ScmMethodProviderCollection.cs Updated as part of this pull request.
packages/​http-client-csharp/​generator/​Microsoft.TypeSpec.Generator.ClientModel/​src/​Providers/​MrwSerializationTypeDefinition.cs Updated as part of this pull request.
packages/​http-client-csharp/​eng/​scripts/​Generation.psm1 Updated as part of this pull request.
packages/​http-client-csharp/​eng/​scripts/​Generate.ps1 Updated as part of this pull request.
packages/​http-client-csharp/​emitter/​test/​Unit/​utils/​test-util.ts Updated as part of this pull request.
packages/​http-client-csharp/​emitter/​src/​type/​input-type.ts Updated as part of this pull request.
packages/​http-client-csharp/​emitter/​src/​type/​code-model.ts Updated as part of this pull request.
packages/​http-client-csharp/​emitter/​src/​lib/​type-converter.ts Updated as part of this pull request.
packages/​http-client-csharp/​emitter/​src/​lib/​client-model-builder.ts Updated as part of this pull request.

Review effort: Balanced

Comment on lines +181 to +184
if (unionType.BaseModel != null)
{
type = CreateCSharpType(unionType.BaseModel);
break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 89d780d. The reference map now preserves the declared variants of a supported discriminated union when its base is publicly reachable, without making unrelated descendants public. UnionDog now generates as public, including its model-factory method. Added reference-map regressions for reachable and disconnected bases and runtime assertions on the emitted types' accessibility.

--generated by Copilot

…iants

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 5, 2026 20:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical generator defects can produce uncompilable SDKs and broken union handling through duplicate signatures, unsuppressed experimental references, abstract payload deserialization, and incorrect JSONL serialization and parsing.

5 open issues
1 resolved since last review
1 file not reviewed
  • packages/http-client-csharp/package-lock.json: Generated file

Review effort: Balanced

foreach (var union in ScmCodeModelGenerator.Instance.InputLibrary.InputNamespace.Unions
.Where(union => union.BaseModel == _inputModel && DiscriminatedUnionSerialization.RequiresEnvelope(union)))
{
methods.AddRange(DiscriminatedUnionSerialization.BuildMethods(union, this));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ab0bab4. Both union helpers now carry reference suppressions from the base and payload variants, including customized CLR-type attributes. Added a regression checking both helpers and an experimental payload in the generated sample; the sample compiles without warnings and the variant round-trips.

--generated by Copilot

Comment on lines +181 to +184
if (unionType.BaseModel != null)
{
type = CreateCSharpType(unionType.BaseModel);
break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ab0bab4 using the raw-data fallback for JSONL items containing envelope unions. JSONL requests take IAsyncEnumerable, and responses use the raw JSONL parser rather than attempting to deserialize the abstract base. The JSONL writer now writes BinaryData as raw JSON, not base64. Added request/response regressions for direct, nullable, array, and dictionary union items, plus generated-client coverage verifying the envelope bytes are preserved. Nonstreaming union operations retain their typed representation.

--generated by Copilot

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 5, 2026 22:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical issues in alternate-type mappings, inherited union helpers, and XML deserialization can prevent generated SDK compilation, while JSONL byte serialization can emit invalid JSON.

9 open issues
1 resolved since last review
1 file not reviewed
  • packages/http-client-csharp/package-lock.json: Generated file

Review effort: Balanced


const base = union.baseType;
if (
union.discriminatedOptions?.envelope === "object" &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 51441b4. Externally mapped unions are excluded from envelope handling, including the CLR-type compatibility check. Their bases are not made abstract solely because of those unions. The generated JsonElement sample uses the existing request/response serialization path and preserves the envelope in both directions.

--generated by Copilot

Comment on lines +490 to +491
union.discriminatedOptions?.envelope === "object" &&
base?.kind === "model" &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 51441b4. Unions with externally mapped bases retain the BinaryData fallback, and no envelope helpers are generated or called on the external base. The generated System.Object sample also exposed an invalid JsonModelWriteCore override on its payload model; that writer is now virtual when the framework base has no serialization method, while existing MRW-base overrides remain intact. Added generation and raw request/response round-trip coverage.

--generated by Copilot

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 5, 2026 23:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 00:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…cestry

Reserve descendant members when naming union helpers, retain patch-aware collection traversal for union envelopes, and fall back to raw data when mapped intermediate ancestors break inheritance.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 01:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a shared hierarchy check for union type mapping, envelope serialization, and reachability, including hand-authored base replacements. Reserve enclosing type names against fully prefixed union helper names.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 02:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Comment on lines +275 to +279
var inputBase = CodeModelGenerator.Instance.InputLibrary.InputNamespace.Models
.FirstOrDefault(candidate => GetProvider(candidate)?.HasTypeIdentity(type) == true);
if (inputBase is not null)
{
return ReachesBase(inputBase, visited);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 66c492b. Serialization now orders the type checks by the resolved C# inheritance chain rather than the nominal TypeSpec hierarchy, so a customized B : A is dispatched before A and writes the b discriminator. Added regressions for both direct rebasing and a custom-only intermediate base, plus generated runtime round-trips that verify each variant's discriminator, CLR type, and payload.

--generated by Copilot

Comment on lines +271 to +275
if (GetProvider(unionBase)?.HasTypeIdentity(type) == true)
{
return true;
}
var inputBase = CodeModelGenerator.Instance.InputLibrary.InputNamespace.Models

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 66c492b. Unqualified generated base types now resolve by provider name, consistent with ModelProvider's existing base resolution. Traversal through custom-only intermediate types also reads their source base information, preserving generated parents that Roslyn cannot resolve yet. Removed the hand-authored Pet and OtherPet stubs from the fixture; the compatible direct/intermediate cases now pass without them, while incompatible base replacements still use BinaryData.

--generated by Copilot

Preserve request-aware constructor metadata and union discriminator handling, combine emitter tests and samples, and regenerate merged C# outputs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 02:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Resolve generated base identities before their sources exist and order union variant dispatch by the customized C# inheritance chain. Cover direct and custom-only intermediate bases without generated-type stubs, plus discriminator round-trips.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 03:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Reserve descendant model deserializer names and inherited union helper names along resolved C# hierarchies. Reuse resolved hierarchy traversal for dispatch and naming, with clean-generation regressions and generated runtime round-trips.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 04:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants