合约数据的泛型反序列化:从异常处理程序返回一种类型“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; // ????
}
}
如果反序列化失败,应该从异常块返回什么?
简短回答:
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 参数上添加了一个约束,因此它有一个默认构造函数。