假设我想将一些XML文件反序列化为强类型对象。如果无法反序列化此XML文件(无论出于何种原因),我只需创建一个默认对象并继续正常的应用程序工作流,而不会向用户显示任何错误。 (实际上这个应用程序是作为Windows服务运行的,因此没有用户...例如,想象应用程序尝试加载配置文件,如果失败则只使用默认配置。)
我的问题是如何创建Deserialize()方法,以便通过调用代码很容易使用?我主要担心的是如何处理异常...这是我的研究。
解决方案1:
这是最简单的方法:
public static T Deserialize<T>(string xml)
{
var serializer = new XmlSerializer(typeof (T));
using (var sr = new StreamReader(xml))
using (var reader = XmlReader.Create(sr))
return (T) serializer.Deserialize(reader);
}
我认为在调用代码中使用这个方法会非常困难,因为我必须处理所有可能由这些方法/构造函数抛出的异常。调用代码并不关心它,它只关心操作是否成功。
所以这是我的第二次尝试:
解决方案2:
public static T Deserialize<T>(string xml)
{
try
{
var serializer = new XmlSerializer(typeof (T));
using (var sr = new StreamReader(xml))
using (var reader = XmlReader.Create(sr))
return (T) serializer.Deserialize(reader);
}
catch (ArgumentException ex)
{
throw new XmlDeserializeException(ValidationExceptionMsg, ex);
}
catch (IOException ex)
{
throw new XmlDeserializeException(ValidationExceptionMsg, ex);
}
catch (XmlSchemaException ex)
{
throw new XmlDeserializeException(ValidationExceptionMsg, ex);
}
catch (InvalidOperationException ex)
{
throw new XmlDeserializeException(ValidationExceptionMsg, ex);
}
}
这里我创建了一个名为XmlDeserializeException的自定义异常,并使用它来包装try块中可由方法(在MSDN中指定)抛出的所有异常。现在,调用代码应该只捕获XmlDeserializeException以知道存在错误。但是我不确定这个解决方案有多好...如果我需要创建很多这样的方法,那么所有这些方法都会有很多catch块只能将异常包装到自定义异常中。
所以我想知道下面的代码会更好:
解决方案3:
public static T Deserialize<T>(string xml)
{
try
{
var serializer = new XmlSerializer(typeof (T));
using (var sr = new StreamReader(xml))
using (var reader = XmlReader.Create(sr))
return (T) serializer.Deserialize(reader);
}
catch (Exception ex)
{
throw new XmlDeserializeException(ValidationExceptionMsg, ex);
}
}
这里我捕获一般异常并将其包装在自定义XmlDeserializeException中。这样我减少了代码编写,没有代码冗余,并且杂乱少。调用代码将再次只需捕获XmlDeserializeException,如解决方案2中那样。
我应该使用哪种解决方案?为什么?有没有更好的方法?请记住我想要使用这个Deserialize()方法的场景,这不是一个库/框架,而是一个没有用户交互性的应用程序。
答案 0 :(得分:1)
如果你以相同的方式处理异常,那么在捕获不同的情况下确实没有意义,在这种情况下,你会将杂乱的情况降到最低,并采用解决方案3.
解决方案2只需要更多代码来完成同样的事情。
答案 1 :(得分:1)
在你的问题中你说:
我想说我想将一些XML文件反序列化为强类型 宾语。如果这个XML文件无法反序列化(无论如何) 原因)我只想创建一个默认对象并继续正常 应用程序工作流程,不会向用户显示任何错误。
如果你没有对异常做任何事情(如你所述,没有用户界面,只有窗口服务),你可以记录你的异常,并返回default(T)
而不是传播异常,如下所示:
public static T Deserialize<T>(string xml)
{
try
{
var serializer = new XmlSerializer(typeof (T));
using (var sr = new StreamReader(xml))
using (var reader = XmlReader.Create(sr))
return (T) serializer.Deserialize(reader);
}
catch (Exception ex)
{
// Log exception here:
Logger.Log(...)
return default(T);
}
}
答案 2 :(得分:1)
我假设您的Deserialize
操作位于由业务组件调用的技术组件中;所以我会尽量保持简洁:
public static T Deserialize<T>(string xml)
{
try
{
var serializer = new XmlSerializer(typeof (T));
using (var sr = new StreamReader(xml))
using (var reader = XmlReader.Create(sr))
return (T) serializer.Deserialize(reader);
}
catch (Exception)
{
// clean up if needed
throw; // throw and keep stack trace
}
在您的调用者或一般错误处理组件中,您可以捕获该异常;并采取行动;例如,执行日志记录(包括堆栈跟踪),将异常转换为业务异常等。
请注意:
Deserialize
操作中,您重新抛出异常,保持堆栈跟踪 Deserialize
操作中抛出异常,请勿返回状态。如果是例外,抛弃它,不要吞下它并依赖状态。