【问题标题】:AutoMapper: Why is this exception not caughtAutoMapper:为什么没有捕获到这个异常
【发布时间】:2011-04-12 05:58:47
【问题描述】:

我已经更新了我的问题,因为我意识到我的代码是导致原始问题的原因。然而,在进一步调查该问题时,我现在在映射过程中遇到了我的代码中发生的异常,但我无法在我的映射表达式扩展中捕获。

基本上,当“dictionaryKey”包含字典中未找到的值时,下面的代码将抛出 keynotfoundexception。就 Automapper 而言,字典保存在被映射的源对象中,请求的 dictionaryKeys 来自目标对象(要映射到)的属性:

public dynamic GetValue(string dictionaryKey)
{
   return _dictionary[dictionaryKey].Value;
}

automapper 扩展类如下所示,我已将 cmets 添加到导致调用上述代码并引发异常的行中。问题是它没有被周围的代码捕获,而是一直被抛出到 Mapper.Map<...>(...) 调用。是什么导致了这个问题,为什么 try catch 块中没有捕获到异常(我添加了断点以确认 try/catch 块中的代码在 GetValue(...) 中抛出了异常。

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

更新 虽然在 GetValue 调用中引发了“未找到键异常”,但它被包裹在 AutoMapper.AutoMappingException 中,该异常在下面的行中冒泡:

客户customer = Mapper.Map(record);

当然,为这些对象调用 Mapper.Map 将触发我的 IMappingExpression 实现,以按照它的设置进行映射:

Mapper.CreateMap().ConvertFromDictionary(propName => propName);

由于 Automapper 是一个围绕 automapper 内部工作原理的静态包装类,这是否是该异常未在 IMappingExpression 的实现中捕获的原因,而是冒泡到触发 map 调用本身的代码?

【问题讨论】:

  • 你到底想达到什么目的?
  • 我正在学习 automapper 并遇到了一些问题 - 在这种情况下,我试图(按名称)映射基本上相当于字典中的名称/值对的内容目标类中的属性。如果目标类包含不在字典中的属性,则会引发异常(如您所料)。但是我无法捕获异常,exp.ForMember 调用包含引发异常的代码,但围绕它的 try/catch 不会捕获异常。我正在尝试了解原因以及我可以做些什么来解决它。

标签: automapper


【解决方案1】:

伙计,这可能是一个愚蠢的问题,但为什么不在允许数据访问字典之前执行 containsKey?

【讨论】:

  • 这里要问的实际问题是为什么 try/catch 块不处理异常 - 而是由其他东西处理,重新引发并在堆栈的更高位置捕获 - 不是我们想要发生。但这是一个很好的观点,这里的代码只是在更大、更复杂的代码中复制问题。如果我们可以摆脱它,我们不想向 ContainsKey 添加检查,因为这会更改代码库只是为了解决自动映射器。理想情况下,我们的映射表达式最终将能够处理这个问题(通过在那里进行正确的检查不会引发异常)。
【解决方案2】:

这是在黑暗中拍摄的,但是否有可能抛出的“异常”实际上并非源自异常?注意问题“Why is UnhandledExceptionEventArgs.ExceptionObject an object and not an Exception?”的答案:

这不能输入到 Exception,因为可能会在 .Net 中抛出不是从 System.Exception 派生的对象。这在 C# 或 VB.Net 中是不可能的,但在其他基于 CLR 的语言中是可能的。因此 API 必须支持这种可能性并使用类型对象。

因此,虽然它不应该为 null,但实际上它可能不是 System.Exception。

有关详细信息,请参阅 CLI 规范第 10.5 节(特别是 CLS 规则 40)

【讨论】:

  • 我的代码抛出的异常是 KeyNotFoundException (这是意料之中的)。在调试模式下,我可以看到它被抛出,然后它最终成为 Automapper.AutoMapperMappingException 的内部异常(这又是另一个 Automapper.AutoMapperMappingException 的内部异常)
猜你喜欢
  • 1970-01-01
  • 2011-11-28
  • 2022-01-06
  • 2012-03-03
  • 2012-08-14
  • 2017-06-18
  • 2021-04-13
  • 2012-01-01
相关资源
最近更新 更多