合约数据的泛型反序列化:从异常处理程序返回一种类型“T”

本文关键字:一种 类型 返回 数据 泛型 反序列化 异常处理程序 | 更新日期: 2023-09-27 17:57:08

我可能无意中违反了这里的设计模式。如果你能解释我做错了什么,我会修补我的方式。

我想编写一个通用的 json 反序列化程序,它返回所提供类型的对象:

public T DeserializeContractData<T>(HttpContext context)
        {
            try
            {
                var obj = (T)new DataContractJsonSerializer(typeof(T)).ReadObject(context.Request.InputStream);
                return obj;
            }
            catch (Exception ex)
            {
                return;   // ????
            }
        }

如果反序列化失败,应该从异常块返回什么?

合约数据的泛型反序列化:从异常处理程序返回一种类型“T”

简短回答:

return default(T)

不那么简短的回答:

it depends :)

取决于返回default值(对于类为 null,结构的默认实例)对您来说是否合适。

如果可以接受,那么我建议您将方法命名为:DeserializeContractDataOrDefault - 这将使事情更加明显。

如果您不能接受(我同意@BlueM,一般来说最好让调用者处理错误) - 那么最好:

  • 不处理异常,让调用方处理;
  • 处理异常(可选地记录它)重新抛出它;
  • 处理异常(可选地记录它)以更详细的方式重新抛出新的异常解释和原始的内在;

我可以建议的另一种方法是添加一些智能逻辑来提供回退值。像这样:

public T DeserializeContractData<T>(HttpContext context, Func<HttpContext, T> getFallbackValue = null)
        {
            try
            {
                var obj = (T)new DataContractJsonSerializer(typeof(T)).ReadObject(context.Request.InputStream);
                return obj;
            }
            catch (Exception ex)
            {
                if(getFallbackValue == null)
                {
                     throw;
                }
                return getFallbackValue(context);
            }
        }

调用者能够通过getFallbackValue提供任何逻辑,因此明智地使用它。

在异常情况下(日志记录等)您还有什么想做的吗? 如果没有,你可以只使用 as 关键字(使用 @aleksey.berezan 的默认 (T) 建议):

public static T DeserializeContractData<T>(HttpContext context)
{
    var obj = new DataContractionJsonSerializer(typeof(T))
                  .ReadObject(context.Request.InputStream)
              as T;
    return obj ?? default(T);
}

或者,只需从该方法中删除异常处理,并让它的任何用途都这样做。 通常,除非有明确的理由使用异常,否则我尽量不使用异常......好吧,除非最好吞下异常。 一般来说,我不喜欢它们用于"包罗万象"的情况。

正如我所建议的,使用 Json.NET 而不是尝试创建自定义反序列化程序:

    public T DeserializeContractData<T>(HttpContext context) where T: new()
    {
        try
        {
            using (var inputStream = new StreamReader(context.Request.InputStream))
            {
                var json = inputStream.ReadToEnd();
                return JsonConvert.DeserializeObject<T>(json);
            }
        }
        catch (JsonSerializationException e)
        {
            //maybe do some logging...
            return default(T);
        }
    }

我在 T 参数上添加了一个约束,因此它有一个默认构造函数。