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 MartinAssuming 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.
精彩评论