【问题标题】:AutoMapper using the wrong constructorAutoMapper 使用了错误的构造函数
【发布时间】:2012-06-24 05:31:18
【问题描述】:

今天我使用 AutoMapper v1.1 将一个功能齐全的应用程序升级到现在使用 AutoMapper v2.1,我遇到了一些使用以前版本从未遇到过的问题。

这是我的代码从 Dto 映射回 Domain 对象

的示例
public class TypeOne
{
   public TypeOne()
   {
   }

   public TypeOne(TypeTwo two)
   {
      //throw ex if two is null
   }

   public TypeOne(TypeTwo two, TypeThree three)
   {
      //throw ex if two or three are null
   }

   public TypeTwo Two {get; private set;}

   public TypeThree Three {get; private set;}
}

public class TypeOneDto
{
   public TypeOneDto()
   {
   }

   public TypeTwoDto Two {get; set;}

   public TypeThreeDto Three {get; set;}
}

...

Mapper.CreateMap<TypeThreeDto, TypeThree>();
Mapper.CreateMap<TypeTwoDto, TypeTwo>();
Mapper.CreateMap<TypeOneDto, TypeOne>();

var typeOne = Mapper.Map<TypeOne>(typeOneDto);

然而,我在 v2.1 中遇到的第一个问题是 AutoMapper 尝试使用带有 2 个 args 的构造函数,而其中一个 args 为 null 并且应该使用 1 个 arg 构造函数。

然后我尝试使用

Mapper.CreateMap<TypeOneDto, TypeOne>().ConstructUsing(x => new TypeOne());

但我不断收到无法解决的“模糊调用”错误。

然后我尝试了

Mapper.CreateMap<TypeOneDto, TypeOne>().ConvertUsing(x => new TypeOne());

并且确实使用无参数构造函数成功创建了 TypeOne 对象,但随后它未能设置私有 setter 属性。

我已经在 AutoMapper 网站上寻求帮助并下载了源代码以进行查看,但对于关于 ConstructUsing 的小文档并没有走得太远,并且没有很多单元测试。

有什么明显的我遗漏的东西我应该用 v2.1 改变吗?我很惊讶它与 v1.1 相比发生了如此大的变化。

【问题讨论】:

标签: c# automapper automapper-2


【解决方案1】:

你只需要将explicit cast添加到

Func<ResolutionContext, TypeOne>

代码如下:

Mapper.CreateMap<TypeOneDto, TypeOne>().ConstructUsing(
            (Func<ResolutionContext, TypeOne>) (r => new TypeOne()));

当前版本的 AutoMapper 的工作方式如下所述:

  1. 按参数计数对目标类型构造函数进行排序

    destTypeInfo.GetConstructors().OrderByDescending(ci => ci.GetParameters().Length);
    
  2. 获取参数匹配源属性的第一个构造函数(不检查空值)。在您的情况下,它是带有两个参数的构造函数。

【讨论】:

  • 这只是让我省了一些悲伤。在最新版本的 AutoMapper (3.2.1.0) 上完美运行 :) 谢谢!
  • 虽然这是一篇相当老的帖子,但我很高兴找到它:AutoMapper 认为与构造函数匹配的顺序似乎在 4.0.4 版本中再次发生了变化。为避免出现问题,如果您有多个构造函数,则始终指定 AutoMapper 应使用哪个构造函数可能更为保守。此外,作为第二个建议,进行自动测试,设置所有地图,然后调用Mapper.AssertConfigurationIsValid()。这样你就可以尽早解决问题。编码愉快!
【解决方案2】:

这是一个扩展方法...

    public static void CreateMapWithDefaultConstructor<T, TU>(this Profile profile)
        where TU : class, new()
    {
        profile.CreateMap<T, TU>().ConstructUsing(source => new TU());
    }

【讨论】:

    猜你喜欢
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 2017-01-28
    相关资源
    最近更新 更多