简体   繁体   中英

C# : Better way to code this?

I have a block of code to handle exceptions in my application, which uses an if/else block to obtain the message content.
My code is as follows:

// 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());

This has been improved from the original version, but just want to see if there is a neater, more re-usable solution to this code.
Thanks in advance
Martin

Assuming that this is a routine which gets passed an exception object (and is not directly involved in a try catch block) and assuming the "exception" object derives eventually from Exception, you could concise your code a bit to do

// 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());
    var exceptionMessage = new StringBuilder();  

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

Make sure the catch blocks come in proper order from least generic to most generic.

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 => ...);

Whenever i see those if else if statements i think this must be done easier. In some cases the switch statement can help, but as this question already stated, it is not possible to switch on Type.

So another workaround i commonly use is some kind of Dictionary<Type, something> . Where something depends on what i'd like to do. The maybe best matching construct for your case would something like Dictionary<Type, Func<Exception, string>> which could be used in your case something like this:

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
}

So with this construction you don't have to put all your intelligence into a big if-else statement. Instead you can put them in separate functions (maybe in different classes) to get a better organization of how to handle each type you like to support.

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);

A little compressed, and without comments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM