I've updated my question as I realised that my code was the cause of the original issue. However in investigating the problem further I've now come across an exception that occurs in my code during the mapping process, but I am unable to capture in my mapping expression extension.
Basically the code below will throw a keynotfoundexception when "dictionaryKey" contains a value not found in the dictionary. As far as Automapper is concerned, the dictionary is held in the source object being mapped and the dictionaryKeys requested are from the properties on the target object (to be mapped to):
public dynamic GetValue(string dictionaryKey)
{
return _dictionary[dictionaryKey].Value;
}
The automapper extension class is shown below in full, I've added comments to the line that causes the makes the call to the code above, throwing the exception. The problem is that it's not caught by it's surrounding code, instead is thrown all the way out to the Mapper.Map<...>(...) call. What causes this issue, why is the exception not caught in the try catch block (I've added break points to confirm exception is thrown in GetValue(...) by code within the try/catch block.
public static IMappingExpression<ActiveRecord, TDestination> ConvertFromDictionary<TDestination>(this IMappingExpression<ActiveRecord, TDestination> exp, Func<string, string> propertyNameMapper)
{
foreach (
PropertyInfo pi in typeof (TDestination).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
if (!pi.CanWrite)
continue;
string propertyName = pi.Name;
propertyName = propertyNameMapper(propertyName);
try
{
// The following code will fail when the target read/write property does not exist in the
// source dictionary. This is thrown in GetValue as a KeyNotFoundException. But it is not
// caught in this try/catch. It makes it's way all the way up to the calling code
// i.e. var entity = Mapper.Map<ActiveRecord, EntityDetail>(activeRecord);
exp.ForMember(propertyName, cfg => cfg.MapFrom(r => r.ActiveFields.GetValue(propertyName)));
}
catch (Exception ex)
{
// This is never reached by the exception above
throw ex;
}
}
return exp;
}
UPDATE Whilst the "key not found exception" is thrown in the GetValue call, it is wrapped up in a AutoMapper.AutoMappingException that is bubbled up on the line below:
Customer customer = Mapper.Map(record);
Of course, calling Mapper.Map for these objects will trigger my implementation of IMappingExpression to do the mapping as it was set up as:
Mapper.CreateMap().ConvertFromDictionary(propName => propName);
As Automapper is a static wrapper class around the inner workings of automapper is this the reason that the exception is not caught in the implementation of IMappingExpression, but is bubbled up to the code that triggered the map call itself?