C#:编写此代码的更好方式?

4

我有一段代码来处理应用程序中的异常,它使用if/else块获取消息内容。
我的代码如下:

// define variable to hold exceptions...
var exceptionMessage = new StringBuilder();  
// based on the exception type...  
if (expType == typeof(EntityValidationException))  
{  
    // append the relevant message to the text...  
    exceptionMessage.Append(exception.InnerException.Message);  
}  
else if (expType == typeof(ValidationException))  
{  
    // This is the type of error generated when entities are validated  
    var validationException = (ValidationException)exception;  
    exceptionMessage.Append(validationException.InnerException.Message);  
}  
else if (expType == typeof(DomainSecurityException))  
{  
    // These are security breaches  
    var domainSecurityException = (DomainSecurityException)exception;  
    exceptionMessage.Append(domainSecurityException.InnerException.Message);  
}  
else if (expType == typeof(DomainInternalMessageException))  
{  
    // These are the type of errors generated a System.Exception occurs and is  
    // converted by the exception handling policy to a more friendly format  
    var domainInternalMessageException = (DomainInternalMessageException)exception;  
    exceptionMessage.Append(domainInternalMessageException.ExceptionMessage);  
}
else  
{  
    exceptionMessage.AppendFormat(ErrorMessagesRes.Standard_Error_Format, "Unknown error", exception.InnerException.Message);   
}  
// this shows the message as an alert popup...  
this.DisplayJavascriptMessage(exceptionMessage.ToString());

这已经比原始版本有所改进,但我想看看是否有更简洁、更易重复使用的解决方案。 预先感谢。 马丁

1
为什么不使用 switch() 来处理 expType?这样可以让你的代码更有结构性。 - Martin Hennings
1
@Martin:你不能在Type上使用switch - Anton Gogolev
@m.edmondson - 什么不正确?你不能在非整数类型上进行开关切换吗? - Martin S
你可以使用 typeof(Exception).ToString 来开启思考。 - David Mårtensson
еҰӮжһң exception дёҚдёә nullпјҢиҖҢ exception.InnerException дёә null е‘ўпјҹ - SWeko
显示剩余9条评论
5个回答

5
假设这是一个例程,它接收一个异常对象(并且不直接涉及try catch块),假设“exception”对象最终派生自Exception,你可以简化代码来执行。
// define variable to hold exceptions...
            var exceptionMessage = new StringBuilder();

            // based on the exception type...  
            if (exception is EntityValidationException || exception is ValidationException || exception is DomainSecurityException)
            {
                // append the relevant message to the text...  
                exceptionMessage.Append(exception.InnerException.Message);
            }

            else if (expType == typeof(DomainInternalMessageException))
            {
                // These are the type of errors generated a System.Exception occurs and is  
                // converted by the exception handling policy to a more friendly format  
                var domainInternalMessageException = (DomainInternalMessageException)exception;
                exceptionMessage.Append(domainInternalMessageException.ExceptionMessage);
            }
            else
            {
                exceptionMessage.AppendFormat(ErrorMessagesRes.Standard_Error_Format, "Unknown error", exception.InnerException.Message);
            }
            // this shows the message as an alert popup...  
            this.DisplayJavascriptMessage(exceptionMessage.ToString());

2
    var exceptionMessage = new StringBuilder();  

    try
    {
    }
    catch(EntityValidationException exc)
    {  
        exceptionMessage.Append(exc.InnerException.Message);  
    }  
    catch(ValidationException exc)  
    {  
        exceptionMessage.Append(exc.InnerException.Message);  
    }  
    ....

确保捕获块按从最具体到最通用的正确顺序排列。


这是一个网络应用程序,我们希望处理错误,将异常消息传递到日志文件,并显示一个简单的错误页面,而不是应用程序崩溃并显示错误堆栈。它可以工作,但在审查代码时,我想知道是否可以改进。 - Martin S
1
@thecoop - 问题中的代码没有显示抛出了什么。 - Jakub Konecki
应该使用此 try 块包装原始异常源。 - Shimmy Weitzhandler
@Jukub Konecki - 谢谢,但是异常已经被传递进来了,因此try/catch块不起作用。我正在使用这个异常来记录并将其转换为友好的消息。 - Martin S
@Jukub Konecki - 抱歉。目前,每个aspx页面事件都使用try/catch块,并将任何异常传递给此过程。然后,它尝试查找类型并获取消息详细信息。我不想改变它的处理方式,因为我们已经进行了太多开发工作,但我只是试图使代码在未来更易读和可重用。感谢迄今为止提出的所有建议。 - Martin S

2
public static Exception On<T>(this Exception e, Action<T> action)
{
    if(e is T)
        action((T)e);

    return e;
}

exception.
    On<ValidationException>(e => exceptionMessage.Append(e.InnerException.Message)).
    On<DomainInternalMessageException>(e => ...);

@Martin S:将On方法作为某个静态类的成员,并使用这个大括号方法调用链重写你的异常处理代码。 - Anton Gogolev
好的,但是我在使用on方法时遇到了一个错误,尝试将类型为'System.Exception'的表达式强制转换为类型'T'。 - Martin S
我尝试实现@Anton的代码,但在方法中遇到了转换错误;不确定如何处理我想要在On方法中执行更多操作而不仅仅是附加到stringbuilder对象中,并且我是否可以简单地将On<Exception>传递到链中以处理其他情况? - Martin S

1
每当我看到那些 if else if 语句时,我就会想这一定可以更简单地完成。在某些情况下,switch 语句可能有所帮助,但正如 this question 已经说明的那样,无法根据类型进行切换。
因此,我通常使用一些类似于 Dictionary<Type, something> 的解决方法。其中的 something 取决于我想要做什么。对于你的情况,最好的匹配构造可能是像这样的 Dictionary<Type, Func<Exception, string>>,它可以在你的情况下像这样使用:
Dictionary<Type, Func<Exception, string>> _FunctorsForType;

private void InitializeFunctorsForType()
{
    _FunctorsForType = new Dictionary<Type, Func<Exception, string>>();

    // Add a normal function
    _FunctorsForType.Add(typeof(ArgumentException), (Func<Exception, string>)ForArgumentException);

    // Add as lambda
    _FunctorsForType.Add(typeof(InvalidCastException), (ex) =>
        {
            // ToDo: Whatever you like
            return ex.Message;
        });
}

private string ForArgumentException(Exception ex)
{
    var argumentException = ex as ArgumentException;

    if (argumentException == null)
    {
        throw new ArgumentException("Exception must be of type " + typeof(ArgumentException).Name);
    }

    // ToDo: Whatever you like
    return ex.Message;
}

private void Usage(Type type)
{
    Func<Exception, string> func;

    if (!_FunctorsForType.TryGetValue(type, out func))
    {
        throw new ArgumentOutOfRangeException("Exception type " + type.Name + " is not supported.");
    }

    var message = func(new NullReferenceException());

    // ToDo: Whatever you have to do with your message
}

所以,通过这种构造,您不必将所有智力投入到一个大的if-else语句中。相反,您可以将它们放在单独的函数中(可能在不同的类中),以更好地组织如何处理您想要支持的每种类型。

0
string exceptionMessage;
if (expType == typeof(EntityValidationException) || 
    expType == typeof(ValidationException) ||
    expType == typeof(DomainSecurityException))
  exceptionMessage = exception.InnerException.Message;
else if (expType == typeof(DomainInternalMessageException))  
 exceptionMessage = ((DomainInternalMessageException)exception).ExceptionMessage;
else  
 exceptionMessage = string.Format(ErrorMessagesRes.Standard_Error_Format, "Unknown error", exception.InnerException.Message);  

this.DisplayJavascriptMessage(exceptionMessage);

这是一个简短的压缩版本,没有注释。


谢谢,我正在做一个更简单的版本。我会先看一下安东的回复。 - Martin S
谢谢大家 - 我会离开并审查选项。感谢你们的时间和帮助。 - Martin S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接