Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit e11c78a

Browse files
committed
Make sure to call T's static constructor before using JsConfig<T>, since the static constructor may set OnDeserialized, etc.
1 parent f114af1 commit e11c78a

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

src/ServiceStack.Text/JsConfig.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.IO;
55
using System.Reflection;
6+
using System.Runtime.CompilerServices;
67
using System.Threading;
78
using ServiceStack.Text.Common;
89
using ServiceStack.Text.Json;
@@ -815,6 +816,12 @@ internal static void AddUniqueType(Type type)
815816

816817
public class JsConfig<T>
817818
{
819+
static JsConfig()
820+
{
821+
// Run the type's static constructor (which may set OnDeserialized, etc.) before we cache any information about it
822+
RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle);
823+
}
824+
818825
/// <summary>
819826
/// Always emit type info for this type. Takes precedence over ExcludeTypeInfo
820827
/// </summary>

tests/ServiceStack.Text.Tests/SerializationHookTests.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,20 @@ public void JsonSerializer_Deserialize_hooks_on_sub_class()
100100
Assert.That(deserialized.OnDeserializedTouched, Is.True);
101101
}
102102

103-
private void AddSerializeHooksForType<T>()
103+
[Test]
104+
public void JsonSerializer_Deserialize_hooks_set_in_cctor()
105+
{
106+
// Deserialize without serializing first, so we don't call the static constructor of HookTestCctor, which sets its own OnDeserialized callback.
107+
108+
//var original = new HookTestContainer { Child = new HookTestCctor() };
109+
//var json = JsonSerializer.SerializeToString(original);
110+
const string json = "{\"Child\":{\"OnDeserializingTouched\":false,\"OnDeserializedTouched\":false,\"OnSerializingTouched\":true,\"OnSerializedTouched\":false}}";
111+
112+
var deserialized = JsonSerializer.DeserializeFromString<HookTestContainer>(json);
113+
Assert.That(deserialized.Child.OnDeserializedTouched, Is.True);
114+
}
115+
116+
internal static void AddSerializeHooksForType<T>()
104117
{
105118
Type type = typeof(T);
106119
System.Reflection.MethodInfo[] typeMethods = type.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
@@ -192,5 +205,18 @@ protected void OnSerialized(StreamingContext ctx)
192205
public class HookTestSubClass : HookTestClass
193206
{
194207
}
208+
209+
public class HookTestCctor : HookTestClass
210+
{
211+
static HookTestCctor()
212+
{
213+
AddSerializeHooksForType<HookTestCctor>();
214+
}
215+
}
216+
217+
public class HookTestContainer
218+
{
219+
public HookTestCctor Child { get; set; }
220+
}
195221
}
196222
}

0 commit comments

Comments
 (0)