From 6fbd3c3e5699369cd4e0162ebd4c728b984b7140 Mon Sep 17 00:00:00 2001 From: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> Date: Wed, 25 Sep 2024 12:53:53 -0700 Subject: [PATCH] Support serialization of custom property (#4532) Fixes https://github.com/microsoft/typespec/issues/4266 --- .../MrwSerializationTypeDefinition.cs | 7 +- .../ModelCustomizationTests.cs | 42 +++++ .../SerializationCustomizationTests.cs | 41 +++++ .../CanChangePropertyName.cs | 26 +++ .../CanChangePropertyName/MockInputModel.cs | 12 ++ .../CanChangePropertyName.cs | 169 ++++++++++++++++++ .../CanChangePropertyName/MockInputModel.cs | 12 ++ .../test/TestHelpers/MockHelpers.cs | 3 +- .../src/Providers/ModelProvider.cs | 8 +- .../src/Providers/PropertyProvider.cs | 4 +- .../src/Providers/TypeProvider.cs | 5 +- .../ModelProviders/ModelCustomizationTests.cs | 12 +- 12 files changed, 322 insertions(+), 19 deletions(-) create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/ModelCustomizationTests.cs create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/SerializationCustomizationTests.cs create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/ModelCustomizationTests/CanChangePropertyName.cs create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/ModelCustomizationTests/CanChangePropertyName/MockInputModel.cs create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/SerializationCustomizationTests/CanChangePropertyName.cs create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/SerializationCustomizationTests/CanChangePropertyName/MockInputModel.cs diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs index 0313bee9cf..28df810885 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/MrwSerializationTypeDefinition.cs @@ -1241,11 +1241,10 @@ private static MethodBodyStatement ThrowValidationFailException(ValueExpression /// private MethodBodyStatement[] CreateWritePropertiesStatements() { - var propertyCount = _model.Properties.Count; - List propertyStatements = new(propertyCount); - for (int i = 0; i < propertyCount; i++) + var properties = _model.Properties.Concat(_model.CustomCodeView?.Properties.Where(p => p.WireInfo != null) ?? []); + List propertyStatements = new(); + foreach (var property in properties) { - var property = _model.Properties[i]; // we should only write those properties with a wire info. Those properties without wireinfo indicate they are not spec properties. if (property.WireInfo is not { } wireInfo) { diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/ModelCustomizationTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/ModelCustomizationTests.cs new file mode 100644 index 0000000000..3191a5287b --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/ModelCustomizationTests.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Generator.CSharp.ClientModel.Providers; +using Microsoft.Generator.CSharp.Input; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Providers; +using Microsoft.Generator.CSharp.Tests.Common; +using NUnit.Framework; + +namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers.MrwSerializationTypeDefinitions +{ + public class ModelCustomizationTests + { + [Test] + public async Task CanChangePropertyName() + { + var props = new[] + { + InputFactory.Property("Prop1", InputFactory.Array(InputPrimitiveType.String)) + }; + + var inputModel = InputFactory.Model("mockInputModel", properties: props, usage: InputModelTypeUsage.Json); + var plugin = await MockHelpers.LoadMockPluginAsync( + inputModels: () => [inputModel], + compilation: async () => await Helpers.GetCompilationFromDirectoryAsync()); + + var modelProvider = plugin.Object.OutputLibrary.TypeProviders.Single(t => t is ModelProvider); + var serializationProvider = modelProvider.SerializationProviders.Single(t => t is MrwSerializationTypeDefinition); + Assert.IsNotNull(serializationProvider); + Assert.AreEqual(0, serializationProvider!.Fields.Count); + + // validate the methods use the custom member name + var writer = new TypeProviderWriter(modelProvider); + var file = writer.Write(); + var expected = Helpers.GetExpectedFromFile(); + Assert.AreEqual(Helpers.GetExpectedFromFile(), file.Content); + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/SerializationCustomizationTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/SerializationCustomizationTests.cs new file mode 100644 index 0000000000..0ccd027663 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/SerializationCustomizationTests.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Generator.CSharp.ClientModel.Providers; +using Microsoft.Generator.CSharp.Input; +using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Providers; +using Microsoft.Generator.CSharp.Tests.Common; +using NUnit.Framework; + +namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers.MrwSerializationTypeDefinitions +{ + public class SerializationCustomizationTests + { + [Test] + public async Task CanChangePropertyName() + { + var props = new[] + { + InputFactory.Property("Prop1", InputFactory.Array(InputPrimitiveType.String)) + }; + + var inputModel = InputFactory.Model("mockInputModel", properties: props, usage: InputModelTypeUsage.Json); + var plugin = await MockHelpers.LoadMockPluginAsync( + inputModels: () => [inputModel], + compilation: async () => await Helpers.GetCompilationFromDirectoryAsync()); + + var modelProvider = plugin.Object.OutputLibrary.TypeProviders.Single(t => t is ModelProvider); + var serializationProvider = modelProvider.SerializationProviders.Single(t => t is MrwSerializationTypeDefinition); + Assert.IsNotNull(serializationProvider); + Assert.AreEqual(0, serializationProvider!.Fields.Count); + + // validate the methods use the custom member name + var writer = new TypeProviderWriter(serializationProvider); + var file = writer.Write(); + Assert.AreEqual(Helpers.GetExpectedFromFile(), file.Content); + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/ModelCustomizationTests/CanChangePropertyName.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/ModelCustomizationTests/CanChangePropertyName.cs new file mode 100644 index 0000000000..74166a8696 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/ModelCustomizationTests/CanChangePropertyName.cs @@ -0,0 +1,26 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Sample.Models +{ + /// mockInputModel description. + public partial class MockInputModel + { + /// Keeps track of any properties unknown to the library. + private protected global::System.Collections.Generic.IDictionary _additionalBinaryDataProperties; + + internal MockInputModel() + { + } + + internal MockInputModel(global::System.String[] prop2, global::System.Collections.Generic.IDictionary additionalBinaryDataProperties) + { + Prop2 = prop2; + _additionalBinaryDataProperties = additionalBinaryDataProperties; + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/ModelCustomizationTests/CanChangePropertyName/MockInputModel.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/ModelCustomizationTests/CanChangePropertyName/MockInputModel.cs new file mode 100644 index 0000000000..b19814f8bf --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/ModelCustomizationTests/CanChangePropertyName/MockInputModel.cs @@ -0,0 +1,12 @@ +#nullable disable + +using Microsoft.Generator.CSharp.Customization; + +namespace Sample.Models +{ + public partial class MockInputModel + { + [CodeGenMember("Prop1")] + public string[] Prop2 { get; set; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/SerializationCustomizationTests/CanChangePropertyName.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/SerializationCustomizationTests/CanChangePropertyName.cs new file mode 100644 index 0000000000..a31206c319 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/SerializationCustomizationTests/CanChangePropertyName.cs @@ -0,0 +1,169 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using Sample; + +namespace Sample.Models +{ + /// + public partial class MockInputModel : global::System.ClientModel.Primitives.IJsonModel + { + void global::System.ClientModel.Primitives.IJsonModel.Write(global::System.Text.Json.Utf8JsonWriter writer, global::System.ClientModel.Primitives.ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + this.JsonModelWriteCore(writer, options); + writer.WriteEndObject(); + } + + /// The JSON writer. + /// The client options for reading and writing models. + protected virtual void JsonModelWriteCore(global::System.Text.Json.Utf8JsonWriter writer, global::System.ClientModel.Primitives.ModelReaderWriterOptions options) + { + string format = (options.Format == "W") ? ((global::System.ClientModel.Primitives.IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if ((format != "J")) + { + throw new global::System.FormatException($"The model {nameof(global::Sample.Models.MockInputModel)} does not support writing '{format}' format."); + } + if (global::Sample.Optional.IsDefined(Prop2)) + { + writer.WritePropertyName("prop1"u8); + writer.WriteStartArray(); + foreach (var item in Prop2) + { + if ((item == null)) + { + writer.WriteNullValue(); + continue; + } + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (((options.Format != "W") && (_additionalBinaryDataProperties != null))) + { + foreach (var item in _additionalBinaryDataProperties) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (global::System.Text.Json.JsonDocument document = global::System.Text.Json.JsonDocument.Parse(item.Value)) + { + global::System.Text.Json.JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + } + + global::Sample.Models.MockInputModel global::System.ClientModel.Primitives.IJsonModel.Create(ref global::System.Text.Json.Utf8JsonReader reader, global::System.ClientModel.Primitives.ModelReaderWriterOptions options) => ((global::Sample.Models.MockInputModel)this.JsonModelCreateCore(ref reader, options)); + + /// The JSON reader. + /// The client options for reading and writing models. + protected virtual global::Sample.Models.MockInputModel JsonModelCreateCore(ref global::System.Text.Json.Utf8JsonReader reader, global::System.ClientModel.Primitives.ModelReaderWriterOptions options) + { + string format = (options.Format == "W") ? ((global::System.ClientModel.Primitives.IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if ((format != "J")) + { + throw new global::System.FormatException($"The model {nameof(global::Sample.Models.MockInputModel)} does not support reading '{format}' format."); + } + using global::System.Text.Json.JsonDocument document = global::System.Text.Json.JsonDocument.ParseValue(ref reader); + return global::Sample.Models.MockInputModel.DeserializeMockInputModel(document.RootElement, options); + } + + internal static global::Sample.Models.MockInputModel DeserializeMockInputModel(global::System.Text.Json.JsonElement element, global::System.ClientModel.Primitives.ModelReaderWriterOptions options) + { + if ((element.ValueKind == global::System.Text.Json.JsonValueKind.Null)) + { + return null; + } + global::System.String[] prop2 = default; + global::System.Collections.Generic.IDictionary additionalBinaryDataProperties = new global::Sample.ChangeTrackingDictionary(); + foreach (var prop in element.EnumerateObject()) + { + if (prop.NameEquals("prop1"u8)) + { + if ((prop.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null)) + { + continue; + } + global::System.Collections.Generic.List array = new global::System.Collections.Generic.List(); + foreach (var item in prop.Value.EnumerateArray()) + { + if ((item.ValueKind == global::System.Text.Json.JsonValueKind.Null)) + { + array.Add(null); + } + else + { + array.Add(item.GetString()); + } + } + prop2 = array; + continue; + } + if ((options.Format != "W")) + { + additionalBinaryDataProperties.Add(prop.Name, global::System.BinaryData.FromString(prop.Value.GetRawText())); + } + } + return new global::Sample.Models.MockInputModel(prop2, additionalBinaryDataProperties); + } + + global::System.BinaryData global::System.ClientModel.Primitives.IPersistableModel.Write(global::System.ClientModel.Primitives.ModelReaderWriterOptions options) => this.PersistableModelWriteCore(options); + + /// The client options for reading and writing models. + protected virtual global::System.BinaryData PersistableModelWriteCore(global::System.ClientModel.Primitives.ModelReaderWriterOptions options) + { + string format = (options.Format == "W") ? ((global::System.ClientModel.Primitives.IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + switch (format) + { + case "J": + return global::System.ClientModel.Primitives.ModelReaderWriter.Write(this, options); + default: + throw new global::System.FormatException($"The model {nameof(global::Sample.Models.MockInputModel)} does not support writing '{options.Format}' format."); + } + } + + global::Sample.Models.MockInputModel global::System.ClientModel.Primitives.IPersistableModel.Create(global::System.BinaryData data, global::System.ClientModel.Primitives.ModelReaderWriterOptions options) => ((global::Sample.Models.MockInputModel)this.PersistableModelCreateCore(data, options)); + + /// The data to parse. + /// The client options for reading and writing models. + protected virtual global::Sample.Models.MockInputModel PersistableModelCreateCore(global::System.BinaryData data, global::System.ClientModel.Primitives.ModelReaderWriterOptions options) + { + string format = (options.Format == "W") ? ((global::System.ClientModel.Primitives.IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + switch (format) + { + case "J": + using (global::System.Text.Json.JsonDocument document = global::System.Text.Json.JsonDocument.Parse(data)) + { + return global::Sample.Models.MockInputModel.DeserializeMockInputModel(document.RootElement, options); + } + default: + throw new global::System.FormatException($"The model {nameof(global::Sample.Models.MockInputModel)} does not support reading '{options.Format}' format."); + } + } + + string global::System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(global::System.ClientModel.Primitives.ModelReaderWriterOptions options) => "J"; + + /// The to serialize into . + public static implicit operator BinaryContent(global::Sample.Models.MockInputModel mockInputModel) + { + return global::System.ClientModel.BinaryContent.Create(mockInputModel, global::Sample.ModelSerializationExtensions.WireOptions); + } + + /// The to deserialize the from. + public static explicit operator MockInputModel(global::System.ClientModel.ClientResult result) + { + using global::System.ClientModel.Primitives.PipelineResponse response = result.GetRawResponse(); + using global::System.Text.Json.JsonDocument document = global::System.Text.Json.JsonDocument.Parse(response.Content); + return global::Sample.Models.MockInputModel.DeserializeMockInputModel(document.RootElement, global::Sample.ModelSerializationExtensions.WireOptions); + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/SerializationCustomizationTests/CanChangePropertyName/MockInputModel.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/SerializationCustomizationTests/CanChangePropertyName/MockInputModel.cs new file mode 100644 index 0000000000..b19814f8bf --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/MrwSerializationTypeDefinitions/TestData/SerializationCustomizationTests/CanChangePropertyName/MockInputModel.cs @@ -0,0 +1,12 @@ +#nullable disable + +using Microsoft.Generator.CSharp.Customization; + +namespace Sample.Models +{ + public partial class MockInputModel + { + [CodeGenMember("Prop1")] + public string[] Prop2 { get; set; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs index c573c6e0eb..a16c7c47e0 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs @@ -24,9 +24,10 @@ internal static class MockHelpers public static async Task> LoadMockPluginAsync( Func>? inputEnums = null, + Func>? inputModels = null, Func>? compilation = null) { - var mockPlugin = LoadMockPlugin(inputEnums: inputEnums); + var mockPlugin = LoadMockPlugin(inputEnums: inputEnums, inputModels: inputModels); var compilationResult = compilation == null ? null : await compilation(); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ModelProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ModelProvider.cs index fbcb0c2965..783657a3b1 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ModelProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ModelProvider.cs @@ -85,6 +85,8 @@ public ModelProvider? BaseModelProvider internal bool SupportsBinaryDataAdditionalProperties => AdditionalPropertyProperties.Any(p => p.Type.ElementType.Equals(_additionalPropsUnknownType)); public ConstructorProvider FullConstructor => _fullConstructor ??= BuildFullConstructor(); + internal IReadOnlyList AllSpecProperties => Properties.Concat(CustomCodeView?.Properties.Where(p => p.WireInfo != null) ?? []).ToList(); + protected override string GetNamespace() => CodeModelPlugin.Instance.Configuration.ModelNamespace; protected override CSharpType? GetBaseType() @@ -465,7 +467,7 @@ private ConstructorProvider BuildFullConstructor() baseParameters.AddRange(BaseModelProvider.FullConstructor.Signature.Parameters); } - HashSet overriddenProperties = Properties.Where(p => p.BaseProperty is not null).Select(p => p.BaseProperty!).ToHashSet(); + HashSet overriddenProperties = AllSpecProperties.Where(p => p.BaseProperty is not null).Select(p => p.BaseProperty!).ToHashSet(); // add the base parameters, if any foreach (var property in baseProperties) @@ -476,7 +478,7 @@ private ConstructorProvider BuildFullConstructor() // construct the initializer using the parameters from base signature var constructorInitializer = new ConstructorInitializer(true, [.. baseParameters.Select(p => GetExpressionForCtor(p, overriddenProperties, isPrimaryConstructor))]); - foreach (var property in Properties) + foreach (var property in AllSpecProperties) { AddInitializationParameterForCtor(constructorParameters, property, Type.IsStruct, isPrimaryConstructor); } @@ -603,7 +605,7 @@ private MethodBodyStatement GetPropertyInitializers( List methodBodyStatements = new(Properties.Count + 1); Dictionary parameterMap = parameters?.ToDictionary(p => p.Name) ?? []; - foreach (var property in Properties) + foreach (var property in AllSpecProperties) { // skip those non-spec properties if (property.WireInfo == null) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/PropertyProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/PropertyProvider.cs index 7c787971b7..d56284fbce 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/PropertyProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/PropertyProvider.cs @@ -28,7 +28,7 @@ public class PropertyProvider public PropertyBody Body { get; internal set; } public CSharpType? ExplicitInterface { get; } public XmlDocProvider XmlDocs { get; private set; } - public PropertyWireInformation? WireInfo { get; } + public PropertyWireInformation? WireInfo { get; internal set; } public bool IsDiscriminator { get; } public bool IsAdditionalProperties { get; init; } @@ -44,8 +44,6 @@ public class PropertyProvider internal IEnumerable? Attributes { get; init; } - internal PropertyProvider? SpecProperty { get; set; } - // for mocking #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. protected PropertyProvider() diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs index eb23b6ee87..00f4b78510 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs @@ -363,8 +363,9 @@ private bool ShouldGenerate(PropertyProvider property) if (customPropertyReplacements.TryGetValue(property.Name, out PropertyProvider? customProp)) { - // Store the spec property on the custom property so that we can use it for serialization. - customProp.SpecProperty = property; + // Store the wire info on the custom property so that we can use it for serialization. + customProp.WireInfo = property.WireInfo; + customProp.BaseProperty = property.BaseProperty; return false; } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Providers/ModelProviders/ModelCustomizationTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Providers/ModelProviders/ModelCustomizationTests.cs index fb5ac44adb..f2623e6ec8 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Providers/ModelProviders/ModelCustomizationTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Providers/ModelProviders/ModelCustomizationTests.cs @@ -51,9 +51,9 @@ public async Task CanChangePropertyName() // the property should be added to the custom code view Assert.AreEqual(1, modelTypeProvider.CustomCodeView!.Properties.Count); Assert.AreEqual("Prop2", modelTypeProvider.CustomCodeView.Properties[0].Name); - var specProperty = modelTypeProvider.CustomCodeView.Properties[0].SpecProperty; - Assert.IsNotNull(specProperty); - Assert.AreEqual( "Prop1", specProperty!.Name); + var wireInfo = modelTypeProvider.CustomCodeView.Properties[0].WireInfo; + Assert.IsNotNull(wireInfo); + Assert.AreEqual( "prop1", wireInfo!.SerializedName); Assert.AreEqual(0, modelTypeProvider.Properties.Count); } @@ -79,9 +79,9 @@ public async Task CanChangePropertyNameAndRedefineOriginal() // the properties should be added to the custom code view Assert.AreEqual(2, modelTypeProvider.CustomCodeView!.Properties.Count); Assert.AreEqual("Prop2", modelTypeProvider.CustomCodeView.Properties[0].Name); - var specProperty = modelTypeProvider.CustomCodeView.Properties[0].SpecProperty; - Assert.IsNotNull(specProperty); - Assert.AreEqual( "Prop1", specProperty!.Name); + var wireInfo = modelTypeProvider.CustomCodeView.Properties[0].WireInfo; + Assert.IsNotNull(wireInfo); + Assert.AreEqual( "prop1", wireInfo!.SerializedName); Assert.AreEqual("Prop1", modelTypeProvider.CustomCodeView.Properties[1].Name); Assert.AreEqual(0, modelTypeProvider.Properties.Count);