是否有与 StreamReader 的 Peek 方法等效的异步等价物?



我正在更新一些netstandard2.0代码,使其不同步从HttpRequest.Body(Stream(读取(这会引发异常netcoreapp3.0除非您设置AllowSynchronousIO选项,这显然不是一个好主意(。

我已经转换了 JSON 反序列化部分(使用System.Text.Json(,但在此之前,它使用StreamReader进行了偷偷摸摸的.Peek()(以查看主体是对象还是数组(,我不确定在哪里寻找异步且不会消耗Stream的现代替代方案。

using var reader = new StreamReader(stream);
switch (reader.Peek()) // TODO: Find an async equivalent!
{
case '{':
return await JsonSerializer.DeserializeAsync<GraphQLRequest>(stream);
case '[':
return await JsonSerializer.DeserializeAsync<GraphQLRequest[]>(stream);
default:
// ...
}

实际上,Peek方法首先将流读入其缓冲区,然后从中为您提供值(查看dotnet运行时存储库(。所以它移动了流的位置。但是,如果不读取并因此查找流,则无法实现速览功能。

由于您无法返回 HttpRequestStream,因此更好的策略是读取整个内容,然后使用Utf8JsonReader来确定请求是对象还是数组。请注意,Utf8JsonReader不能在异步方法中声明,因此我不得不将其放在单独的非异步方法中。

private static JsonTokenType GetTokenType(byte[] bytes)
{
var reader = new Utf8JsonReader(bytes.AsSpan());
reader.Read();
return reader.TokenType;
}
var ms = new MemoryStream();
await Request.Body.CopyToAsync(ms);
var jsonBytes = ms.ToArray();
switch (GetTokenType(jsonBytes)) 
{
case JsonTokenType.StartObject:
return JsonSerializer.Deserialize<GraphQLRequest>(jsonBytes);
case JsonTokenType.StartArray:
return JsonSerializer.Deserialize<GraphQLRequest[]>(jsonBytes);
default:
// ...
}

由于我们的独特情况,在对此进行了反复讨论之后,我们(幸运的是!(得到了@davidfowl的帮助,他们使用PipeReader为我们提供了一个示例,这是一种AdvanceTo方法,可以查看令牌但不使用流,因此我们可以直接从流中使用Deserialize

完整的来源在这里。

相关内容

  • 没有找到相关文章

最新更新