2014-06-23 27 views
2

情况1:假设您的业务层中有复杂的检查或计算,并且计算失败,因为某些数据错误或丢失。例如,您捕获一个计算异常。带参数的本地化错误消息

Sceneraio 2:想象一下,您在业务层中查询数据层(数据库),并且发现缺少记录异常。

任务:您现在处于业务层,挂在catch块中,但有一个尚未解决的异常。您想通知用户由于参数X与参数Y不匹配而需要本地化错误消息(为了简单起见,您有两种语言),因此出现错误。

的问题:

  • 一)你如何传播错误的表示层。
  • b)您将如何本地化错误并保留消息中的参数?如:“尊敬的用户计算失败,因为数据X不匹配的数据Y”

提出的答案:

  • a)你扔从业务层具有以前作为另一个异常内部异常。
  • b)这是我正在寻找的关键答案。假设您可以承担给出的参数值,因为它是一个Intranet应用程序,用户需要知道这些参数是错误的。

的问题是关于应用程序设计 - 如何“翻译/本地化例外”或向用户显示一个翻译/本地化错误消息,当你在代码中的点异常被捕获,并且可以存在多个异常与多个消息。

异常消息采用统一的语言,采用英文。

+0

我没有得到你提出的答案的含义,但@ private_meta的答案对你的案例来说非常有用和直接。 –

+0

这个问题是关于概念,如果你愿意的话,而不是如何将参数插入字符串 - “每个人”都知道。 – Santhos

+0

我想知道还有什么地方可以提出这样的问题,如果你觉得太过分了。我还没有找到任何有关它的好文章,我认为这是一个非常普遍的情况,很多程序员都在这里遇到困难。 – Santhos

回答

1

我们在我们的应用程序中执行此操作。我们采取的方法是:

  1. 在服务层没有发现错误。允许所有异常传播回原始调用的表示层方法。

  2. 在数据访问层中抛出自定义异常。通常,如果在查询数据库时发生数据访问异常,则会引发数据库特定的错误。在数据访问层捕获该异常,但将其包装在自定义异常中。我们有一个名为DataAccessException的枚举属性,该枚举属性指示哪个数据访问层调用导致了错误,另一个属性指示错误的原因是与访问相关(权限不足)还是因为数据库抛出错误。

  3. 捕获表示层中的所有错误。在调用服务层的表示层方法中,有一个try-catch块。每个异常类型通常会有一个catch子句,您期望由较低层中的代码引发该异常类型。在该catch块中,您将创建本地化消息,将其记录到事件日志中(如果有),并将错误显示给用户。

  4. 所有可本地化的字符串应该是资源字符串。这并不是一条硬性规则,但使用资源字符串方法意味着它可以轻松添加对Windows未来支持的其他语言的支持。您为每个不会更改的字符串定义资源标识符。每个字符串所需的参数数量也不会改变。所有这些变化都是字符串,“{0}”,“{1}”等参数出现在字符串中。

编辑

我回答您的评论在这里,因为响应时间比我可以适合在一个评论。

根据我在特定catch块中处理的异常创建本地化消息。我尝试使错误消息可读。也就是说,你必须假设读者完全不懂任何编程知识。你描述一般情况下出了什么问题;最好不要提到确切的例外情况。例如,尝试打开文件时出现FileNotFoundException的消息应该显示为“找不到名为”{0}“的文件,请确保您正确输入了文件名。”如果家中有人不是程序员,只要想一想你如何向他们解释问题&你可能会有一个好消息。

至于要给它什么资源键,我使用命名约定。对于我们的MVC网络应用程序,约定是<控制器> <动作> <消息名称>。一旦定义了密钥,代码将始终使用密钥来检索该消息,方法是请求该属性与VS构建的ResourceManager中的密钥名称相同。

在您构建资源字符串时由VS创建的ResourceManager类使用区域设置来确定要检索哪个本地语言消息字符串。返回的字符串以及所需的任何参数将传递到string.Format,并显示或记录结果。

我们在代码中有一条规则,即消息字符串的参数始终是不需要转换为其他语言的东西。也就是说,用户输入的字符串,或者数字或日期都可以,但枚举值不是。这是因为我们的Web应用程序显示自身和Windows WPF应用程序生成的审核消息,并且不知道WPF应用程序中的任何枚举。由于ResourceManagerpartial类,因此您可以轻松地向其添加方法,以便按照您的要求对枚举进行本地化。这是你的控制。然后,您可以调用该方法对枚举值进行本地化,然后将其传递到string.Format,您需要这样做。

+0

你如何创建本地化的消息?它是基于异常的类型还是异常携带一些额外的数据(如资源字符串)? – Santhos

+0

感谢您的辛苦评论/编辑。这正是我很想知道的 - 其他人如何处理这种情况。这个问题也许要广泛地问,但我还没有找到任何关于它的好文章。 – Santhos

1

我会这样做的通常方式是本地化格式字符串。你的资源包括格式字符串,像这样:

string errorString "Dear user the computation has failed because data {0} does not match data {1}"; 

当抛出该异常或显示错误,你只需要插入数据

string.Format(errorString, dataX, dataY); 

编辑:当你想在你的异常文本统一的语言,并且您不希望稍后将异常类型映射到资源字符串,最好的选择是将资源字符串提供给您的异常以及数据,或让您的异常携带原始消息并将翻译消息在同一时间。

映射问题的另一个选择是您可以使用反射。这样,您就可以使用您的异常类型,并在资源中查找所述类型,而无需显式映射它们。您将转到您的资源并查找名为的属性,例如“Error_MyCustomException”。这会给你每个异常类型一个自定义消息,你必须存储的是数据。

+0

问题不在于如何将参数插入到字符串中。问题是如何“翻译例外”,如何将信息(例外)从业务层转移到表示层,然后翻译它。您有多个消息的多个例外。 – Santhos

+0

这取决于您希望您的翻译/本地化发生的位置。你想让你的例外已经翻译过了吗?只需将资源字符串放入异常本身即可。你想只显示翻译的消息,只有在实际显示它时才获取资源字符串。如果这不是问题,我真的不明白你的问题。 –

+0

例外情况是统一的语言。问题是在哪里存储或如何检索资源字符串,但我想唯一的方法是定制例外,以便他们携带资源字符串。问题基本上是关于设计 - 你将如何抛出并捕获异常并向用户显示本地化的错误消息。在我看来,翻译异常消息之前,先向用户展示它们。我是“仅代码中的英语”的主角。 – Santhos