9
9
using System . Text ;
10
10
using System . Text . Encodings . Web ;
11
11
using System . Text . Json ;
12
+ using System . Text . Json . Serialization ;
12
13
using Microsoft . AspNetCore . Internal ;
13
14
using Microsoft . AspNetCore . SignalR . Protocol ;
14
15
using Microsoft . Extensions . Options ;
@@ -106,6 +107,106 @@ public void MagicCast()
106
107
Assert . Equal ( expectedMessage , message ) ;
107
108
}
108
109
110
+ [ Fact ]
111
+ public void PolymorphicWorksWithInvocation ( )
112
+ {
113
+ Person todo = new JsonPersonExtended ( )
114
+ {
115
+ Name = "Person" ,
116
+ Age = 99 ,
117
+ } ;
118
+
119
+ var expectedJson = "{\" type\" :1,\" target\" :\" method\" ,\" arguments\" :[{\" $type\" :\" JsonPersonExtended\" ,\" age\" :99,\" name\" :\" Person\" ,\" child\" :null,\" parent\" :null}]}" ;
120
+
121
+ var writer = MemoryBufferWriter . Get ( ) ;
122
+ try
123
+ {
124
+ JsonHubProtocol . WriteMessage ( new InvocationMessage ( "method" , new [ ] { todo } ) , writer ) ;
125
+
126
+ var json = Encoding . UTF8 . GetString ( writer . ToArray ( ) ) ;
127
+ Assert . Equal ( Frame ( expectedJson ) , json ) ;
128
+
129
+ var binder = new TestBinder ( [ typeof ( JsonPerson ) ] ) ;
130
+ var data = new ReadOnlySequence < byte > ( Encoding . UTF8 . GetBytes ( json ) ) ;
131
+ Assert . True ( JsonHubProtocol . TryParseMessage ( ref data , binder , out var message ) ) ;
132
+
133
+ var invocationMessage = Assert . IsType < InvocationMessage > ( message ) ;
134
+ Assert . Equal ( 1 , invocationMessage . Arguments ? . Length ) ;
135
+ PersonEqual ( todo , invocationMessage . Arguments [ 0 ] ) ;
136
+ }
137
+ finally
138
+ {
139
+ MemoryBufferWriter . Return ( writer ) ;
140
+ }
141
+ }
142
+
143
+ [ Fact ]
144
+ public void PolymorphicWorksWithStreamItem ( )
145
+ {
146
+ Person todo = new JsonPersonExtended ( )
147
+ {
148
+ Name = "Person" ,
149
+ Age = 99 ,
150
+ } ;
151
+
152
+ var expectedJson = "{\" type\" :2,\" invocationId\" :\" 1\" ,\" item\" :{\" $type\" :\" JsonPersonExtended\" ,\" age\" :99,\" name\" :\" Person\" ,\" child\" :null,\" parent\" :null}}" ;
153
+
154
+ var writer = MemoryBufferWriter . Get ( ) ;
155
+ try
156
+ {
157
+ JsonHubProtocol . WriteMessage ( new StreamItemMessage ( "1" , todo ) , writer ) ;
158
+
159
+ var json = Encoding . UTF8 . GetString ( writer . ToArray ( ) ) ;
160
+ Assert . Equal ( Frame ( expectedJson ) , json ) ;
161
+
162
+ var binder = new TestBinder ( typeof ( JsonPerson ) ) ;
163
+ var data = new ReadOnlySequence < byte > ( Encoding . UTF8 . GetBytes ( json ) ) ;
164
+ Assert . True ( JsonHubProtocol . TryParseMessage ( ref data , binder , out var message ) ) ;
165
+
166
+ var streamItemMessage = Assert . IsType < StreamItemMessage > ( message ) ;
167
+ Assert . Equal ( "1" , streamItemMessage . InvocationId ) ;
168
+ PersonEqual ( todo , streamItemMessage . Item ) ;
169
+ }
170
+ finally
171
+ {
172
+ MemoryBufferWriter . Return ( writer ) ;
173
+ }
174
+ }
175
+
176
+ [ Fact ]
177
+ public void PolymorphicWorksWithCompletion ( )
178
+ {
179
+ Person todo = new JsonPersonExtended2 ( )
180
+ {
181
+ Name = "Person" ,
182
+ Location = "Canada" ,
183
+ } ;
184
+
185
+ var expectedJson = "{\" type\" :3,\" invocationId\" :\" 1\" ,\" result\" :{\" $type\" :\" JsonPersonExtended2\" ,\" location\" :\" Canada\" ,\" name\" :\" Person\" ,\" child\" :null,\" parent\" :null}}" ;
186
+
187
+ var writer = MemoryBufferWriter . Get ( ) ;
188
+ try
189
+ {
190
+ JsonHubProtocol . WriteMessage ( CompletionMessage . WithResult ( "1" , todo ) , writer ) ;
191
+
192
+ var json = Encoding . UTF8 . GetString ( writer . ToArray ( ) ) ;
193
+ Assert . Equal ( Frame ( expectedJson ) , json ) ;
194
+
195
+ var binder = new TestBinder ( typeof ( JsonPerson ) ) ;
196
+ var data = new ReadOnlySequence < byte > ( Encoding . UTF8 . GetBytes ( json ) ) ;
197
+ Assert . True ( JsonHubProtocol . TryParseMessage ( ref data , binder , out var message ) ) ;
198
+
199
+ var completionMessage = Assert . IsType < CompletionMessage > ( message ) ;
200
+ Assert . Equal ( "1" , completionMessage . InvocationId ) ;
201
+ Assert . True ( completionMessage . HasResult ) ;
202
+ PersonEqual ( todo , completionMessage . Result ) ;
203
+ }
204
+ finally
205
+ {
206
+ MemoryBufferWriter . Return ( writer ) ;
207
+ }
208
+ }
209
+
109
210
public static IDictionary < string , JsonProtocolTestData > CustomProtocolTestData => new [ ]
110
211
{
111
212
new JsonProtocolTestData ( "InvocationMessage_HasFloatArgument" , new InvocationMessage ( null , "Target" , new object [ ] { 1 , "Foo" , 2.0f } ) , true , true , "{\" type\" :1,\" target\" :\" Target\" ,\" arguments\" :[1,\" Foo\" ,2]}" ) ,
@@ -119,4 +220,72 @@ public void MagicCast()
119
220
} . ToDictionary ( t => t . Name ) ;
120
221
121
222
public static IEnumerable < object [ ] > CustomProtocolTestDataNames => CustomProtocolTestData . Keys . Select ( name => new object [ ] { name } ) ;
223
+
224
+ private class Person
225
+ {
226
+ public string Name { get ; set ; }
227
+ public Person Child { get ; set ; }
228
+ public Person Parent { get ; set ; }
229
+ }
230
+
231
+ [ JsonPolymorphic ]
232
+ [ JsonDerivedType ( typeof ( JsonPersonExtended ) , nameof ( JsonPersonExtended ) ) ]
233
+ [ JsonDerivedType ( typeof ( JsonPersonExtended2 ) , nameof ( JsonPersonExtended2 ) ) ]
234
+ private class JsonPerson : Person
235
+ { }
236
+
237
+ private class JsonPersonExtended : JsonPerson
238
+ {
239
+ public int Age { get ; set ; }
240
+ }
241
+
242
+ private class JsonPersonExtended2 : JsonPerson
243
+ {
244
+ public string Location { get ; set ; }
245
+ }
246
+
247
+ private static void PersonEqual ( object expected , object actual )
248
+ {
249
+ if ( expected is null && actual is null )
250
+ {
251
+ return ;
252
+ }
253
+
254
+ Assert . Equal ( expected . GetType ( ) , actual . GetType ( ) ) ;
255
+
256
+ if ( expected is JsonPersonExtended expectedPersonExtended && actual is JsonPersonExtended actualPersonExtended )
257
+ {
258
+ Assert . Equal ( expectedPersonExtended . Name , actualPersonExtended . Name ) ;
259
+ Assert . Equal ( expectedPersonExtended . Age , actualPersonExtended . Age ) ;
260
+ PersonEqual ( expectedPersonExtended . Child , actualPersonExtended . Child ) ;
261
+ PersonEqual ( expectedPersonExtended . Parent , actualPersonExtended . Parent ) ;
262
+ return ;
263
+ }
264
+
265
+ if ( expected is JsonPersonExtended2 expectedPersonExtended2 && actual is JsonPersonExtended2 actualPersonExtended2 )
266
+ {
267
+ Assert . Equal ( expectedPersonExtended2 . Name , actualPersonExtended2 . Name ) ;
268
+ Assert . Equal ( expectedPersonExtended2 . Location , actualPersonExtended2 . Location ) ;
269
+ PersonEqual ( expectedPersonExtended2 . Child , actualPersonExtended2 . Child ) ;
270
+ PersonEqual ( expectedPersonExtended2 . Parent , actualPersonExtended2 . Parent ) ;
271
+ return ;
272
+ }
273
+
274
+ if ( expected is JsonPerson expectedJsonPerson && actual is JsonPerson actualJsonPerson )
275
+ {
276
+ Assert . Equal ( expectedJsonPerson . Name , actualJsonPerson . Name ) ;
277
+ PersonEqual ( expectedJsonPerson . Child , actualJsonPerson . Child ) ;
278
+ PersonEqual ( expectedJsonPerson . Parent , actualJsonPerson . Parent ) ;
279
+ return ;
280
+ }
281
+
282
+ if ( expected is Person expectedPerson && actual is Person actualPerson )
283
+ {
284
+ Assert . Equal ( expectedPerson . Name , actualPerson . Name ) ;
285
+ PersonEqual ( expectedPerson . Parent , actualPerson . Parent ) ;
286
+ PersonEqual ( expectedPerson . Child , actualPerson . Child ) ;
287
+ }
288
+
289
+ Assert . False ( true , "Passed in unexpected object(s)" ) ;
290
+ }
122
291
}
0 commit comments