Ensure JSON deserializer only uses Activator.CreateInstance implicitly for structs

This commit is contained in:
Steve Sanderson 2018-03-29 10:39:59 +01:00
parent 25cf73ed80
commit f15c995a2a
2 changed files with 23 additions and 15 deletions

View File

@ -1430,7 +1430,7 @@ namespace SimpleJson
obj = value; obj = value;
else else
{ {
obj = ConstructorCache[type]?.Invoke() ?? Activator.CreateInstance(type); obj = ConstructorCache[type]();
foreach (KeyValuePair<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> setter in SetCache[type]) foreach (KeyValuePair<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> setter in SetCache[type])
{ {
object jsonValue; object jsonValue;
@ -1851,6 +1851,14 @@ namespace SimpleJson
public static ConstructorDelegate GetConstructorByReflection(Type type, params Type[] argsType) public static ConstructorDelegate GetConstructorByReflection(Type type, params Type[] argsType)
{ {
ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType); ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType);
if (constructorInfo == null && argsType.Length == 0 && type.IsValueType)
{
// If it's a struct, then parameterless constructors are implicit
// We can always call Activator.CreateInstance in lieu of a zero-arg constructor
return args => Activator.CreateInstance(type);
}
return constructorInfo == null ? null : GetConstructorByReflection(constructorInfo); return constructorInfo == null ? null : GetConstructorByReflection(constructorInfo);
} }

View File

@ -84,40 +84,40 @@ namespace Microsoft.AspNetCore.Blazor.Test
public void CanSerializeStructToJson() public void CanSerializeStructToJson()
{ {
// Arrange // Arrange
var commandResult = new SimpleError var commandResult = new SimpleStruct
{ {
Message = "Test", StringProperty = "Test",
ContainsError = true, BoolProperty = true,
ErrorId = 1 NullableIntProperty = 1
}; };
// Act // Act
var result = JsonUtil.Serialize(commandResult); var result = JsonUtil.Serialize(commandResult);
// Assert // Assert
Assert.Equal("{\"Message\":\"Test\",\"ContainsError\":true,\"ErrorId\":1}", result); Assert.Equal("{\"StringProperty\":\"Test\",\"BoolProperty\":true,\"NullableIntProperty\":1}", result);
} }
[Fact] [Fact]
public void CanDeserializeStructFromJson() public void CanDeserializeStructFromJson()
{ {
// Arrange // Arrange
var json = "{\"Message\":\"Test\",\"ContainsError\":true,\"ErrorId\":1}"; var json = "{\"StringProperty\":\"Test\",\"BoolProperty\":true,\"NullableIntProperty\":1}";
//Act //Act
var simpleError = JsonUtil.Deserialize<SimpleError>(json); var simpleError = JsonUtil.Deserialize<SimpleStruct>(json);
// Assert // Assert
Assert.Equal("Test", simpleError.Message); Assert.Equal("Test", simpleError.StringProperty);
Assert.True(simpleError.ContainsError); Assert.True(simpleError.BoolProperty);
Assert.Equal(1, simpleError.ErrorId); Assert.Equal(1, simpleError.NullableIntProperty);
} }
struct SimpleError struct SimpleStruct
{ {
public string Message { get; set; } public string StringProperty { get; set; }
public bool ContainsError { get; set; } public bool BoolProperty { get; set; }
public int? ErrorId { get; set; } public int? NullableIntProperty { get; set; }
} }
class Person class Person