MapsterMapper/Mapster

Cannot CompileProjection for a mapping derived types between abstract classes with .Include()

Aberta

#801 aberto em 7 de mai. de 2025

 (9 comentários) (0 reação) (0 responsável)C# (312 forks)batch import
help wantedimprovement

Métricas do repositório

Stars
 (3.995 estrelas)
Métricas de merge de PR
 (Mesclagem média 12d 15h) (10 fundiu PRs em 30d)

Description

Description

When trying to create a mapping between abstract base classes and including their derived concrete implementations, Mapster throws an exception during CompileProjection(). There appears to be an issue in the expression tree generation.

Environment

  • Mapster version: 7.4.0
  • Mapster.EFCore 5.1.1
  • .NET version: net9.0
  • EF Core version: 9.0.4

I have tried Mapster 7.4.2-pre02 with net9.0 and net8.0 as well.

Steps to Reproduce

  1. Define the following class hierarchy:
public abstract class PocoA
{
    public int Id { get; set; }
}

public class PocoDerived : PocoA
{
    public int DerivedVal { get; set; }
}

public abstract class DtoA
{
    public int Id { get; set; }
}

public class DtoDerived : DtoA
{
    public int DerivedVal { get; set; }
}
  1. Configure the mapping:
config.NewConfig<PocoA, DtoA>()
    .Include<PocoDerived, DtoDerived>();
  
config.CompileProjection();

Alternatively, edit the WhenIncludeDerivedClasses test in Mapster.Tests so that the Compile() lines are CompileProjection();

Expected Behavior

The mapping should compile successfully, allowing for projection between these types.

Actual Behavior

An exception is thrown during CompileProjection():

Unhandled exception. Mapster.CompileException: Error while compiling
source=Backend.Services.Models.PocoA
destination=Backend.Services.Models.DtoA
type=Projection
 ---> System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.UnaryExpression' to type 'System.Linq.Expressions.NewExpression'.
   at Mapster.Adapters.ClassAdapter.CreateInlineExpression(Expression source, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateInlineExpressionBody(Expression source, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
   at Mapster.Adapters.BaseAdapter.CreateAdaptFunc(CompileArgument arg)
   at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
   --- End of inner exception stack trace ---
   at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
   at Mapster.TypeAdapterConfig.CreateMapExpression(TypeTuple tuple, MapType mapType)
   at Mapster.TypeAdapterConfig.CreateProjectionCallExpression(TypeTuple tuple)
   at Mapster.TypeAdapterConfig.CompileProjection()

Guia do colaborador