Skip to content

Commit c4b7c86

Browse files
committed
Support serialization of System.Type
1 parent ad90815 commit c4b7c86

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.cs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ internal static class DataSerializationHelper
2121
#if NETFRAMEWORK
2222
DataContractSurrogate = SerializationSurrogateProvider.Instance,
2323
#endif
24-
KnownTypes = [typeof(SurrogatedDateOnly), typeof(SurrogatedTimeOnly)],
24+
KnownTypes = [typeof(SurrogatedDateOnly), typeof(SurrogatedTimeOnly), typeof(SurrogatedSystemType)],
2525
};
2626

2727
/// <summary>
@@ -163,6 +163,13 @@ private sealed class SurrogatedTimeOnly
163163
public long Ticks { get; set; }
164164
}
165165

166+
[DataContract]
167+
private sealed class SurrogatedSystemType
168+
{
169+
[DataMember]
170+
public string AssemblyQualifiedName { get; set; } = null!;
171+
}
172+
166173
private sealed class SerializationSurrogateProvider
167174
#if NETFRAMEWORK
168175
: IDataContractSurrogate
@@ -190,20 +197,15 @@ public object GetDeserializedObject(object obj, Type targetType)
190197
=> GetDeserializedObject(obj);
191198

192199
internal static object GetDeserializedObject(object obj)
193-
{
194-
#if NET6_0_OR_GREATER
195-
if (obj is SurrogatedDateOnly surrogatedDateOnly)
196-
{
197-
return DateOnly.FromDayNumber(surrogatedDateOnly.DayNumber);
198-
}
199-
else if (obj is SurrogatedTimeOnly surrogatedTimeOnly)
200+
=> obj switch
200201
{
201-
return new TimeOnly(surrogatedTimeOnly.Ticks);
202-
}
202+
#if NET6_0_OR_GREATER
203+
SurrogatedDateOnly surrogatedDateOnly => DateOnly.FromDayNumber(surrogatedDateOnly.DayNumber),
204+
SurrogatedTimeOnly surrogatedTimeOnly => new TimeOnly(surrogatedTimeOnly.Ticks),
203205
#endif
204-
205-
return obj;
206-
}
206+
SurrogatedSystemType surrogatedSystemType => Type.GetType(surrogatedSystemType.AssemblyQualifiedName) ?? throw new SerializationException(),
207+
_ => obj,
208+
};
207209

208210
public object GetObjectToSerialize(object obj, Type targetType)
209211
=> obj switch
@@ -212,6 +214,7 @@ public object GetObjectToSerialize(object obj, Type targetType)
212214
DateOnly dateOnly => new SurrogatedDateOnly() { DayNumber = dateOnly.DayNumber },
213215
TimeOnly timeOnly => new SurrogatedTimeOnly() { Ticks = timeOnly.Ticks },
214216
#endif
217+
Type type when type.AssemblyQualifiedName is { } typeAssemblyQualifiedName => new SurrogatedSystemType() { AssemblyQualifiedName = typeAssemblyQualifiedName },
215218
_ => obj,
216219
};
217220

@@ -232,7 +235,7 @@ public Type GetSurrogateType(Type type)
232235
}
233236
#endif
234237

235-
return type;
238+
return type.IsAssignableTo(typeof(Type)) ? typeof(SurrogatedSystemType) : type;
236239
}
237240
}
238241
#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT

test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Helpers/DataSerializationHelperTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,14 @@ public void DataSerializerShouldRoundTripTimeOnly()
7979
Verify(actual[0]!.Equals(source));
8080
}
8181
#endif
82+
83+
public void DataSerializerShouldRoundTripSystemType()
84+
{
85+
foreach (Type source in (Type[])[typeof(Console), typeof(DataSerializationHelperTests), typeof(DataSerializationHelper)])
86+
{
87+
object?[]? actual = DataSerializationHelper.Deserialize(DataSerializationHelper.Serialize([source]));
88+
Verify(actual!.Length == 1, $"Deserialization length check failed for type {source.Name}");
89+
Verify((Type)actual[0]! == source, $"Deserialization equality failed for type {source.Name}");
90+
}
91+
}
8292
}

0 commit comments

Comments
 (0)