Is there any way to disable AutoMapper's exception wrapping?
I have a repository that will throw an EntityNotFoundException
when its GetSingle<T>(int id)
method cannot find the requested entity in the database. When I use this with AutoMapper and an exception occurs, I get something like this instead:
AutoMapperMappingException: Trying to map CategoryDTO to Category... --->
AutoMapperMappingException: Trying to map System.Int32 to CategoryType... --->
AutoMapper.MappingException: Trying to map System.Int32 to CategoryType... --->
EntityNotFoundException: entity of type CategoryType with ID 5 was not found in the database
My custom exception is 4 levels down. This makes it hard to use try-catch blocks because now I have to do something like this:
try
{
// do the mapping
}
catch (AutoMapperMappingException e)
{
// get the inner-most exception
while (e.InnerException != null)
{
e = e.InnerException;
}
// check to see if it's an EntityNotFoundException
if (e.GetType() == typeof (EntityNotFoundException))
{
var notFound = e as EntityNotFoundException;
// do something specific here, like inform the user
}
else
{
// do something more generic
}
What I'd like to be able to do is just this:
try
{
// do the mapping
开发者_JAVA技巧}
catch (EntityNotFoundException e)
{
// do something specific here, like inform the user
}
catch (Exception e)
{
// do something more generic
}
Is there any way of disabling AutoMapper's exception wrapping behavior so that I get the straight-up exceptions that are being thrown?
Answer
I ended up creating a thin wrapper around AutoMapper
that will catch the AutoMapperMappingException
, find the inner-most exception, and throw that:
public class AutoMapperWrapper
{
public TB Map<TA, TB>(TA source, TB destination)
{
// try to do the mapping
try
{
return Mapper.Map(source, destination);
}
// catch AutoMapper's exception
catch (Exception e)
{
// find the first InnerException that's not wrapped
while (e is AutoMapperMappingException)
{
e = e.InnerException;
}
// if the inner exception is null, throw the original exception
if (e == null)
{
throw;
}
// otherwise, throw the inner exception
else
{
throw e;
}
}
}
}
The downside of this method though is that sometimes the entire exception tree is useful to look at to see which property or entity mapping AutoMapper failed on, but this code will only give you the inner-most exception, which is sometimes not very helpful by itself, like InvalidCastException
: "could not convert string to int", but won't tell you which property it was.
I thing it would be bad design to conditionally wrap exception so I guess the only thing to do is to drill down into inner exception and find the first none automapperexception.
I've implemented AutoMapperMappingException unwrapping in my NArms.AutoMapper library (see issue). It main purpose is to reduce code amount by providing MapTo<>() extension method which can be used instead of Mapper.Map(). You can get it via NuGet.
Obviously, source code is available at GitHub.
精彩评论