Automapper表达式错误:空引用/映射类型错误和ReverseMap

4

我正在尝试使用AutoMapper在表达式中映射两个模型,但是从AutoMapper收到一个错误:“Error Mapping Types”,并且内部异常消息为“对象引用未设置为对象的实例”。

我按照Github上的wiki设置了我的配置并定义了映射:

Configuration

Expression Translation

下面是一个非常简化的示例,它使用AutoMapper 5.1.1生成错误。

要映射的模型

注意:我只需要从Model1映射到Model2。

public class Model1
{
    public int Id { get; set; }
}

public class Model2
{
    public int Id { get; set; }
} 

配置:

public static class AutoMapperConfig
{
    public static IMapper Mapper;

    static AutoMapperConfig()
    {
        var config = new MapperConfiguration(c => {
          // Produces error
          CreateMap<Model1, Model2>();

          //The below definitions do NOT produce error
          CreateMap<Model1, Model2>().ReverseMap();
          //OR
          CreateMap<Model1, Model2>();
          CreateMap<Model2, Model1>();
          //OR
          CreateMap<Expression<Func<Model1,bool>>, Expression<Func<Model2,bool>>>();

        });

        Mapper = config.CreateMapper();
    }
}

使用方法:

Expression<Func<Model1, bool>> model1Expr = x => x.Id == 2;
var model2Expr =  AutoMapperConfig.Mapper.Map<Expression<Func<Model2,bool>>>(model1Expr);

我在上面声明model2Expr变量的那一行代码收到了错误。

来自Elmah的错误 :(

[NullReferenceException: Object reference not set to an instance of an object.]
AutoMapper.Mappers.MappingVisitor.PropertyMap(MemberExpression node) +109
AutoMapper.Mappers.MappingVisitor.VisitMember(MemberExpression node) +95
System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor) +14
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) +22
AutoMapper.Mappers.MappingVisitor.VisitBinary(BinaryExpression node) +73
System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor) +14
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) +22
AutoMapper.Mappers.ExpressionMapper.Map(TSource expression, ResolutionContext context) +1534
lambda_method(Closure , Object , Object , ResolutionContext ) +183

[AutoMapperMappingException: Error mapping types.

重要提示:一位同事指出,当定义双向映射(使用ReverseMap或两个单独的CreateMap语句)或者将映射明确定义为两个表达式类型之间时,不会遇到错误。上面的Expression Translation链接确实定义了模型之间的双向映射,但没有明确提到需要它。

问题:

我是否在配置和/或映射定义方面出错了,或者在表达式对象之间进行映射时需要双向映射定义,而维基百科只是没有明确说明?


更新: 我在AutoMapper GitHub上开了一个问题。 目前看来,

是的,在进行表达式转换时,顺序是相反的。

基本上这意味着,如果你想在表达式之间进行映射,请按照所需映射的相反方向创建映射定义:

CreateMap<Model2, Model1>();
//....
Expression<Func<Model1, bool>> model1Expr = x => x.Id == 2;
var model2Expr =  AutoMapperConfig.Mapper.Map<Expression<Func<Model2,bool>>>(model1Expr);

使用方法与配置为从Model1对象映射到Model2对象的映射不同。 - Win
@Win 我刚刚尝试了在表达式之间定义单向映射,我没有收到错误。我之前没有尝试过这个方法,因为根据我在Expression Translation wiki中的理解,对象之间的映射定义就足够了。这是不完整文档的情况吗? - kay
Automapper旨在将一个对象的属性映射到另一个对象。为什么要从一个表达式树映射到另一个对象呢?这不应该是Automapper的工作。 - Win
这里有一个与编程高度相关的问题,可能会带来一些见解。问题链接 - Will Ray
在我的特定情况下,我有一个DTO,它是实体模型的表示。我在演示层控制器(ASP.NET MVC)中使用DTO创建了一个lambda表达式。然后将该lambda表达式作为参数传递给业务层方法。业务层方法需要将DTO表达式转换/映射为Entity模型表达式,以便可以将其与Entity Framework一起使用。 - kay
@WillRay 目前的AutoMapper版本似乎支持不同类型表达式之间的映射(请参阅上述的表达式翻译链接)。谢谢你提供的链接,我会参考它来更深入了解表达式树的相关知识。 - kay
1个回答

1
您需要按照以下方式调用ReverseMap:

static AutoMapperConfig()
{
    var config = new MapperConfiguration(c => {
      CreateMap<Model1, Model2>().ReverseMap(); // <======
    });

    Mapper = config.CreateMapper();
}

谢谢您的回答。您能提供说明文档,证明需要使用ReverseMap吗?我的同事也注意到了这个问题,我只是想知道为什么它没有在维基上。 - kay
ReverseMap 不是默认提供的。它被添加到 AutoMapper 中,您必须调用它才能创建它。以下是他们这样做的提交:https://github.com/AutoMapper/AutoMapper/commit/bff6e2aa49af3e7b50f527376da48924efa7d81e - CodingYoshi
抱歉,我的意思是问是否有文档说明必须定义双向映射(使用ReverseMap或两个单独的CreateMap语句)才能正确地在表达式之间进行映射。 - kay
我理解了你的问题。他们实现了ReverseMap方法这一事实意味着它之前并不存在。如果你不定义反向映射,它对于普通对象也无法工作,更别提表达式了。 - CodingYoshi
我在我的映射定义中没有考虑使用ReverseMap,因为我并不需要它。我只需要从Model1映射到Model2。如果AutoMapper需要双向映射定义才能使表达式映射正常工作,这对我来说并不直观,尽管这可能是由于我对表达式树的知识有限。感谢您的澄清。 - kay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接