From db1f36e848e9d05681d5db3def77c911083a8b26 Mon Sep 17 00:00:00 2001 From: josh Date: Mon, 17 May 2021 17:15:28 -0700 Subject: [PATCH] allow the ContractlessStandardResolver to also honor explicitly marked private constructors --- .../Internal/ReflectionExtensions.cs | 7 +++++ .../Resolvers/DynamicObjectResolver.cs | 2 +- .../Tests/ShareTests/AllowPrivateTest.cs | 30 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Internal/ReflectionExtensions.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Internal/ReflectionExtensions.cs index dba621351..8c9956bdd 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Internal/ReflectionExtensions.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Internal/ReflectionExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -48,5 +49,11 @@ public static MethodInfo GetSetMethod(this PropertyInfo propInfo) { return propInfo.SetMethod; } + + public static bool HasPrivateCtorForSerialization(this TypeInfo type) + { + var markedCtor = type.DeclaredConstructors.SingleOrDefault(x => x.GetCustomAttribute(false) != null); + return markedCtor?.Attributes.HasFlag(MethodAttributes.Private) ?? false; + } } } diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/DynamicObjectResolver.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/DynamicObjectResolver.cs index f285082dc..5b9e3a796 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/DynamicObjectResolver.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/DynamicObjectResolver.cs @@ -224,7 +224,7 @@ static FormatterCache() return; } - if (ti.IsAnonymous()) + if (ti.IsAnonymous() || ti.HasPrivateCtorForSerialization()) { Formatter = (IMessagePackFormatter)DynamicObjectTypeBuilder.BuildFormatterToDynamicMethod(typeof(T), true, true, false); return; diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/AllowPrivateTest.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/AllowPrivateTest.cs index 7c418e7ea..505db369e 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/AllowPrivateTest.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/AllowPrivateTest.cs @@ -193,6 +193,25 @@ public ImmutablePrivateClass(int x, int y, bool dummy) public bool CreatedUsingPrivateCtor { get; } } + public class ContractlessClassPrivateCtor + { + public int X { get; private set; } + + public int Y { get; private set; } + + [SerializationConstructor] + private ContractlessClassPrivateCtor(int x, int y) + { + X = x; + Y = y; + } + + public static ContractlessClassPrivateCtor Create(int x, int y) + { + return new ContractlessClassPrivateCtor(x, y); + } + } + [MessagePackObject] public class CompletelyPrivateConstructor { @@ -335,6 +354,17 @@ public void PrivateConstructor2() Assert.Equal(p1.X, p2.X); Assert.Equal(p1.Y, p2.Y); } + + [Fact] + public void ContractlessAttributedPrivateConstructor() + { + var p1 = ContractlessClassPrivateCtor.Create(10, 20); + var bin = MessagePackSerializer.Serialize(p1, ContractlessStandardResolver.Options); + var p2 = MessagePackSerializer.Deserialize(bin, ContractlessStandardResolver.Options); + + Assert.Equal(p1.X, p2.X); + Assert.Equal(p1.Y, p2.Y); + } #endif } }