Skip to content

InvalidCastException when using polymorphic mapping with required properties #906

@DS-DanielW

Description

@DS-DanielW

Seem to have run into somewhat of an issue with v10 of Mapster vs the latest v7 release. Potentially related to the support for required properties?

TypeAdapterConfig.Compile() throws an InvalidCastException when all three of the following conditions are met:

  1. Polymorphic mapping using .Include<TDerived, TDerivedDest>()
  2. Abstract destination type
  3. required properties on the destination type

Removing any one of these conditions either resolves the issue or produces a different (expected) error.

Mapster versions: 10.0.0-10.0.7-pre02
Target framework: net8.0

Minimal Reproduction

using Mapster;

var config = TypeAdapterConfig.GlobalSettings;

config.NewConfig<ConcreteSource, ConcreteDestination>();

config.NewConfig<AbstractSource, AbstractDestination>()
    .Include<ConcreteSource, ConcreteDestination>();

config.Compile(); // Throws InvalidCastException

// --- Source types ---

public abstract class AbstractSource
{
    public abstract string Name { get; }
}

public class ConcreteSource : AbstractSource
{
    public override string Name => "Test";
}

// --- Destination types ---

public abstract class AbstractDestination
{
    public required string Name { get; set; }
}

public class ConcreteDestination : AbstractDestination;

Stack Trace

Mapster.CompileException: Error while compiling
source=AbstractSource
destination=AbstractDestination
type=Map
 ---> 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, Boolean IsRequiredOnly)
   at Mapster.Adapters.BaseAdapter.CreateBlockExpressionBody(Expression source, Expression destination, 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.Compile(Boolean failFast)

Workaround

Remove the required keyword from destination properties and use default initialisers instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions