From 806afeb64bcfda964f622cd737c5ab52304e711c Mon Sep 17 00:00:00 2001 From: ReubenBond Date: Fri, 18 Jun 2021 08:13:22 -0700 Subject: [PATCH] Add C# 9 record support to serializer (#7108) Co-authored-by: Oisin Grehan --- .../Generators/SerializerGenerator.cs | 2 +- .../SerializationTests/RoundTripSerializerTests.cs | 8 ++++++++ test/Grains/TestGrainInterfaces/IValueTypeTestGrain.cs | 10 +++++++++- test/Grains/TestGrainInterfaces/IsExternalInit.cs | 5 +++++ test/Grains/TestGrains/RoundtripSerializationGrain.cs | 5 ++++- 5 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 test/Grains/TestGrainInterfaces/IsExternalInit.cs diff --git a/src/Orleans.CodeGenerator/Generators/SerializerGenerator.cs b/src/Orleans.CodeGenerator/Generators/SerializerGenerator.cs index d6a2ae3d498..b443dbb3029 100644 --- a/src/Orleans.CodeGenerator/Generators/SerializerGenerator.cs +++ b/src/Orleans.CodeGenerator/Generators/SerializerGenerator.cs @@ -794,7 +794,7 @@ public FieldInfoMember(SerializerGenerator generator, SemanticModel model, IName /// /// Gets a value indicating whether or not this field represents a property with an accessible, non-obsolete setter. /// - public bool IsSettableProperty => this.Property?.SetMethod != null && this.model.IsAccessible(0, this.Property.SetMethod) && !this.IsObsolete; + public bool IsSettableProperty => Property?.SetMethod is { } setMethod && model.IsAccessible(0, setMethod) && !setMethod.IsInitOnly && !IsObsolete; /// /// Gets syntax representing the type of this field. diff --git a/test/DefaultCluster.Tests/SerializationTests/RoundTripSerializerTests.cs b/test/DefaultCluster.Tests/SerializationTests/RoundTripSerializerTests.cs index b771be046d5..fff126af183 100644 --- a/test/DefaultCluster.Tests/SerializationTests/RoundTripSerializerTests.cs +++ b/test/DefaultCluster.Tests/SerializationTests/RoundTripSerializerTests.cs @@ -13,6 +13,14 @@ public RoundTripSerializerTests(DefaultClusterFixture fixture) : base(fixture) { } + [Fact] + public async Task Serialize_TestMethodResultRecord() + { + var grain = this.GrainFactory.GetGrain(GetRandomGrainId()); + RetVal retVal = await grain.GetRetValForParamVal(new ParamVal(42)); + Assert.Equal(42, retVal.Value); + } + [Fact] public async Task Serialize_TestMethodResultEnum() { diff --git a/test/Grains/TestGrainInterfaces/IValueTypeTestGrain.cs b/test/Grains/TestGrainInterfaces/IValueTypeTestGrain.cs index f21ebb74cb7..98e7814f08d 100644 --- a/test/Grains/TestGrainInterfaces/IValueTypeTestGrain.cs +++ b/test/Grains/TestGrainInterfaces/IValueTypeTestGrain.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Orleans; @@ -144,8 +144,16 @@ public interface IRoundtripSerializationGrain : IGrainWithIntegerKey Task GetEnemyType(); Task GetClosedGenericValue(); + + Task GetRetValForParamVal(ParamVal param); } + [Serializable] + public record ParamVal(int Value); + + [Serializable] + public record RetVal(int Value); + [Serializable] [Immutable] public class ImmutableType diff --git a/test/Grains/TestGrainInterfaces/IsExternalInit.cs b/test/Grains/TestGrainInterfaces/IsExternalInit.cs new file mode 100644 index 00000000000..f7fc37a017a --- /dev/null +++ b/test/Grains/TestGrainInterfaces/IsExternalInit.cs @@ -0,0 +1,5 @@ +namespace System.Runtime.CompilerServices +{ + // required for record serialization support for downlevel + internal static class IsExternalInit {} +} \ No newline at end of file diff --git a/test/Grains/TestGrains/RoundtripSerializationGrain.cs b/test/Grains/TestGrains/RoundtripSerializationGrain.cs index 37f3f2e71ec..3bba2a99191 100644 --- a/test/Grains/TestGrains/RoundtripSerializationGrain.cs +++ b/test/Grains/TestGrains/RoundtripSerializationGrain.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Threading.Tasks; @@ -20,5 +20,8 @@ public Task GetClosedGenericValue() var result = new List>>>(); return Task.FromResult((object)result); } + + // test record support + public Task GetRetValForParamVal(ParamVal param) => Task.FromResult(new RetVal(param.Value)); } }