检查 Exception catch 块内的异常类型并记录它

Check for exception type inside Exception catch block and log it

我正在使用 Utf8 json 库使用 JsonSerializer class 的 DeserializeAsync 方法反序列化我的 JSON。有时我看到它抛出异常 -

Arithmetic operation resulted in an overflow.

所以看起来我的 JSON 数据的值太大而无法放入我们对象的属性之一,从而导致此溢出异常。下面是我最初的代码,我们没有捕获到从下面的代码中抛出的任何异常 -

using (var content = httpResponseMessage.Content)
{
    if (content == null) return (default(T), statusCode);

    using (var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync())
    {
        deserializedValue = await JsonSerializer.DeserializeAsync<T>(responseStream, formatResolver);
    }
}

所以现在我将上面的代码包装在一个 try catch 中,这样我就可以捕获异常而不是抛出它并记录请求的主体 -

using (var content = httpResponseMessage.Content)
{
    if (content == null) return (default(T), statusCode);

    using (var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync())
    {
        try
        {
            deserializedValue = await JsonSerializer.DeserializeAsync<T>(responseStream, formatResolver);
        }
        catch (JsonParsingException ex)
        {
            var bodyString = ex.GetUnderlyingByteArrayUnsafe();
            var error = (bodyString != null) ? $"Failing json: {bodyString}" : null;
            logger.logError(error, ex.Message, "Deserialization Exception", ex.StackTrace, (int)statusCode);
            return (default(T), HttpStatusCode.BadRequest);
        }
        catch (Exception ex)
        {
            logger.logError("Cannot Deserialize JSON", ex.Message, "Deserialization Exception", ex.StackTrace, (int)statusCode);
            return (default(T), HttpStatusCode.BadRequest);
        }
    }
}

问题陈述

我想看看有没有办法把上面的两个catch块合并起来写在Exception块里面?我尝试使用以下代码,但它在这一行 ex.GetUnderlyingByteArrayUnsafe() 上抱怨,因为它找不到 GetUnderlyingByteArrayUnsafe 方法。我的想法是,如果无法反序列化 json 并在可能的情况下写入一个 catch 块,则记录该请求。

catch (Exception ex)
{
    var bodyString = ex is JsonParsingException? ex.GetUnderlyingByteArrayUnsafe() : null;
    var error = (bodyString != null) ? $"Failing json: {bodyString}" : "Cannot Deserialize JSON";
    logger.logError(error, ex.Message, "Deserialization Exception", ex.StackTrace, (int)statusCode);
    return (default(T), HttpStatusCode.BadRequest);
}

我也在查看 Utf8 json git repo,但我没有看到 DeserializeAsync 方法抛出任何 JsonParsingException 异常?

is 运算符正在对您的异常是否可以转换为目标类型执行布尔运算,但该类型转换不会随后传递给您的三元组的第一个分支。

您可以重铸:

var bodyString = ex is JsonParsingException 
    ? ((JsonParsingException)ex).GetUnderlyingByteArrayUnsafe() 
    : null;

或者您可以使用 as 运算符,它将尝试为您进行转换,如果不能,将 return null:

var jsonParsingException = ex as JsonParsingException;
var bodyString = jsonParsingException != null
    ? jsonParsingException.GetUnderlyingByteArrayUnsafe() 
    : null;

请注意,使用C#7 pattern matching,您还可以将结果输出到临时局部变量并启用one-liner:

var bodyString = ex is JsonParsingException j
    ? j.GetUnderlyingByteArrayUnsafe() 
    : null;

最后,@mjwills 指出您可以将 as 操作包裹在大括号中并使用 null 传播运算符检查 null,同时允许 one-liner:

var bodyString = (ex as JsonParsingException)?.GetUnderlyingByteArrayUnsafe();