Skip to content

C# generator should fully support inheritable system model replacements #10787

@live1206

Description

@live1206

Description

The C# generator has SystemObjectModelProvider, which is a useful building block for mapping an input model to an existing framework/system model while still allowing derived generated models to use it as BaseModelProvider. However, Azure management-plane generation still needs a custom MPG visitor (InheritableSystemObjectModelVisitor) to repair several behaviors after mapping ARM common types like Resource, ProxyResource, and TrackedResource to framework types such as ResourceData and TrackedResourceData.

We would like MTG/ClientModel to provide first-class support for inheritable system model replacement so MPG can remove or significantly shrink this visitor.

Current workaround in MPG

In Azure/azure-sdk-for-net#56634, MPG uses InheritableSystemObjectModelVisitor to:

  1. Register framework CSharpType aliases in CSharpTypeMap so custom-code base types like TrackedResourceData resolve back to the mapped SystemObjectModelProvider.
  2. Repair SystemObjectModelProvider namespace after generic namespace visitors run.
  3. Remove model factory methods returning known framework management types.
  4. Manually remove inherited properties from derived models, including wire-name matches such as a derived Name0 property whose serialized name is name, because the framework base already owns Name.
  5. Strip orphaned virtual modifiers after removing inherited duplicate properties.

Gap in MTG today

SystemObjectModelProvider : ModelProvider already helps with some inheritance behavior:

  • It can serve as BaseModelProvider.
  • It sets ShouldSkipDerivedModelProperties = true.
  • It does not emit fields or serialization providers for the framework type.
  • ModelProvider.BuildProperties() skips derived properties whose C# property name matches a base property from a provider marked ShouldSkipDerivedModelProperties.

But this is not enough for ARM-style common types:

1. Wire-name based property dedup is missing

MTG skips inherited properties by C# property name. MPG also needs wire-name equivalence.

Example:

  • Framework base has Name with wire name name.
  • Derived input model has a generated C# property Name0 but serialized/wire name name.
  • The derived property should be removed because the framework base already represents that wire property.

Without this, generated output can duplicate ARM base properties as renamed properties like Name0.

2. Framework/non-framework CSharpType alias lookup is fragile

Custom code can resolve a base type like TrackedResourceData as a framework CSharpType, while the mapped system provider may be keyed differently. MTG should make the system replacement discoverable under all equivalent CSharpType forms, or compare framework/system replacement types consistently in BuildBaseModelProvider().

3. Namespace rewriting should not corrupt system providers

Generic namespace visitors can rewrite provider namespaces to the SDK namespace. A system/framework provider should keep its framework namespace or otherwise be immune to normal generated-model namespace rewriting.

4. Model factory methods should not be emitted for framework replacements

If an input model is replaced by a framework/system type, model factory methods returning that framework replacement should be skipped by default. MPG currently filters them out.

5. Constructor/field/serialization behavior should fully account for system bases

Once a generator maps an input model to an inheritable framework base, derived models should not duplicate inherited fields/properties/constructor parameters/serialization overrides, including the wire-name equivalence case above.

Desired behavior

A generator should be able to register something equivalent to:

Known ARM model "TrackedResource" -> framework type TrackedResourceData
Known ARM model "Resource" -> framework type ResourceData

Then MTG should handle derived generated models correctly without a management-plane visitor manually walking and editing properties.

Suggested test case

Add a ClientModel/MTG test with:

  • A system base input model representing ResourceData or TrackedResourceData, with properties like id, name, type, tags, location.
  • A derived generated model with a property named name0 whose serialized name is name, plus a normal service-specific property.
  • The base model mapped to a SystemObjectModelProvider/framework type.

Expected:

  • The derived generated model does not emit Name0.
  • It does not duplicate base fields or constructor parameters.
  • Serialization methods call/override appropriately for a system base.
  • Model factory methods for the framework replacement type are not generated.
  • The system provider keeps the framework namespace.

Context

This is needed to simplify Azure management-plane generation and eventually remove more of InheritableSystemObjectModelVisitor from MPG.

Metadata

Metadata

Assignees

Labels

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

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions