forked from microsoft/vstest
-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
TestObjectConverter.cs
199 lines (166 loc) · 7.09 KB
/
TestObjectConverter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Serialization;
/// <summary>
/// JSON converter for the <see cref="TestObject"/> and derived entities.
/// </summary>
public class TestObjectConverter : JsonConverter
{
/// <inheritdoc/>
public override bool CanRead => true;
/// <inheritdoc/>
public override bool CanWrite => false;
/// <inheritdoc/>
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
if (objectType != typeof(List<KeyValuePair<TestProperty, object>>))
{
// Support only deserialization of KeyValuePair list
throw new ArgumentException("the objectType was not a KeyValuePair list", nameof(objectType));
}
var propertyList = new List<KeyValuePair<TestProperty, object?>>();
if (reader.TokenType != JsonToken.StartArray)
{
return propertyList;
}
var properties = JArray.Load(reader);
if (properties == null || !properties.HasValues)
{
return propertyList;
}
// Every class that inherits from TestObject uses a properties store for <Property, Object>
// key value pairs.
foreach (var property in properties)
{
var testProperty = property?["Key"]?.ToObject<TestProperty>(serializer);
if (testProperty == null)
{
continue;
}
// Let the null values be passed in as null data
var token = property?["Value"];
object? propertyData = null;
if (token != null && token.Type != JTokenType.Null)
{
// If the property is already a string. No need to convert again.
if (token.Type == JTokenType.String)
{
propertyData = token.ToObject(typeof(string), serializer);
}
else
{
// On deserialization, the value for each TestProperty is always a string. It is up
// to the consumer to deserialize it further as appropriate.
propertyData = token.ToString(Formatting.None).Trim('"');
}
}
propertyList.Add(new KeyValuePair<TestProperty, object?>(testProperty, propertyData));
}
return propertyList;
}
/// <inheritdoc/>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
// Create an array of <Property, Value> dictionary
}
}
/// TODO: This is not used now, but I was experimenting with this quite a bit for performance, leaving it here in case I was wrong
/// and the serializer settings actually have signigicant impact on the speed.
/// <summary>
/// JSON converter for the <see cref="TestObject"/> and derived entities.
/// </summary>
internal class TestObjectConverter7 : JsonConverter
{
// Empty is not present everywhere
#pragma warning disable CA1825 // Avoid zero-length array allocations
private static readonly object[] EmptyObjectArray = new object[0];
#pragma warning restore CA1825 // Avoid zero-length array allocations
public TestObjectConverter7()
{
#if !NETSTANDARD1_3
TestPropertyCtor = typeof(TestProperty).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
#endif
}
/// <inheritdoc/>
public override bool CanRead => true;
/// <inheritdoc/>
public override bool CanWrite => false;
public ConstructorInfo? TestPropertyCtor { get; }
/// <inheritdoc/>
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
if (objectType != typeof(List<KeyValuePair<TestProperty, object>>))
{
// Support only deserialization of KeyValuePair list
throw new ArgumentException("the objectType was not a KeyValuePair list", nameof(objectType));
}
if (reader.TokenType != JsonToken.StartArray)
{
return new List<KeyValuePair<TestProperty, object>>();
}
var deserializedProperties = serializer.Deserialize<List<KeyValuePair<TestPropertyTemplate, JToken>>>(reader)!;
// Initialize the list capacity to be the number of properties we might add.
var propertyList = new List<KeyValuePair<TestProperty, object?>>(deserializedProperties.Count);
// Every class that inherits from TestObject uses a properties store for <Property, Object>
// key value pairs.
foreach (var property in deserializedProperties)
{
// This call will fail with NRE on .NET Standard 1.3
var testProperty = (TestProperty)TestPropertyCtor!.Invoke(EmptyObjectArray);
testProperty.Id = property.Key.Id!;
testProperty.Label = property.Key.Label!;
testProperty.Category = property.Key.Category!;
testProperty.Description = property.Key.Description!;
testProperty.Attributes = (TestPropertyAttributes)property.Key.Attributes;
testProperty.ValueType = property.Key.ValueType!;
object? propertyData = null;
JToken token = property.Value;
if (token.Type != JTokenType.Null)
{
// If the property is already a string. No need to convert again.
if (token.Type == JTokenType.String)
{
propertyData = token.ToObject(typeof(string), serializer);
}
else
{
// On deserialization, the value for each TestProperty is always a string. It is up
// to the consumer to deserialize it further as appropriate.
propertyData = token.ToString(Formatting.None).Trim('"');
}
}
propertyList.Add(new KeyValuePair<TestProperty, object?>(testProperty, propertyData));
}
return propertyList;
}
/// <inheritdoc/>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
// Create an array of <Property, Value> dictionary
}
private class TestPropertyTemplate
{
public string? Id { get; set; }
public string? Label { get; set; }
public string? Category { get; set; }
public string? Description { get; set; }
public int Attributes { get; set; }
public string? ValueType { get; set; }
}
}