在我的MVC解决方案中,我有两个异常处理程序。首先记录日志数据库的异常:
public sealed class LogErrorAttribute : Attribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
// some handling with filterContext.Exception
}
}第二,向用户显示异常:
public sealed class AsyncAwareHandleErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
// some handling with filterContext.Exception
}
}当发生任何未处理的异常时,它们都会被触发:
throw new ArgumentNullException("email", i18n.someErrorMessage);i18n.someErrorMessage是从resx文件中翻译出来的字符串。
在filterContext.Exception.Message中的两个处理程序中,我都有一个字符串,它已经被翻译过了。
如何仅在CultureInfo.InvariantCulture中记录异常消息,在解决方案中将其设置为en-US?
发布于 2015-02-11 14:42:14
认为异常应该包含自己的人类可读的信息的观点非常普遍,但也非常误导。
在概念上,
异常传递的消息是异常的类型以及异常中包含的任何成员变量。
这也意味着:
对于抛出的每一个概念不同的异常,您都必须有一个不同的异常类。
在抛出通配符"MyAllPurposeException“时,不能通过构造不同的人类可读的消息来区分不同的异常情况。试图从异常中理解的实体不应仅限于人类:从概念上讲,catch块还有权从代码引发的异常中理解,至少在单元测试的上下文中是如此,但通常在生产代码中也是如此。
为了方便起见,我们通常只是在异常中填充一条人类可读的消息,但这只是一个快速而肮脏的解决方案。当您有一个具有实际实际国际化需求的应用程序时,您不可能这样做。
因此,我的建议是永远不要向异常添加任何消息。让Message成员为空白;我甚至可以说,将string Message成员包含在原始Exception类中是代表语言运行时设计人员的一个错误。相反,知道如何处理异常的异常处理程序应该决定是否为该异常生成一个人类可读的消息,如果应该的话,它应该只由程序员或用户读取,因此,区域设置(区域性)应该是什么。
从概念上讲,您将有一个二维表,其中X轴上有区域设置,Y轴上有异常类型名称,而表中的每个单元格都包含一个字符串,如“参数%d不能为空”,使用正确的语言。第一列可能是包含程序员可读的消息的中立区域设置,即不变区域性。
当然,在现实中,它需要稍微复杂一些,因为您必须以某种方式读取异常的特定类型成员,并将它们传递给字符串格式函数。对于您控制的异常,可以添加一个可覆盖的,并按如下方式实现:
public ParameterCannotBeNullException extends MyException
{
private final int parameterNumber;
public ParameterCannotBeNullException( int parameterNumber )
{
this.parameterNumber = parameterNumber;
}
public override String FormatMessage( String localeSpecificMessage )
{
return String.Format( localeSpecificMessage, parameterNumber );
}
}对于无法控制的异常,可以有一个巨大的级联if语句,如下所示:
String formatString = (look it up by exception.GetType() and locale)
String message;
if( exception is SomeException )
{
SomeException temp = (SomeException)exception;
message = String.Format( formatString, temp.X );
}
else if( exception is SomeOtherException )
{
SomeOtherException temp = (SomeOtherException)exception;
message = String.Format( formatString, temp.A, temp.B );
}
else
{
message = exception.GetType().Name;
}最后一件事:有时在编写代码时,我们意识到我们遇到了可能发生错误的情况,因此需要抛出一个新的异常,但我们不想中断我们正在做的事情,并在此时声明一个新的异常类。对于这种情况,我发现有一个GeneralPurposeException是有用的,它实际上在其构造函数中接受包含程序员可读的消息的字符串。但是这个类包含了一个很大的注释,内容如下:
XXX固定TODO: 只供发展之用! 这样的话,阶级就不能去生产!
https://stackoverflow.com/questions/28456930
复制相似问题