Skip to content

Extra mapper parameters do not work with MapDerivedType #1765

Description

@WORMrus

Please do the checklist before filing an issue:

  • [✅] I have read the documentation, including the FAQ
  • [✅] I can reproduce the bug using the latest prerelease version.
  • [✅] I have searched existing discussion and issue to avoid duplicates.

Describe the bug
I need to map a polymorphic item using an additional parameter. It works for concrete types (derivedDto->derived) but I want to declare it as a polymorphic mapper for the base types and provide the additional parameter, Mapperly generates broken mapping code and does not issue any analyzer warnings

This could actually be #1719 but I am not sure. Though it does not seem like it's supposed to break like that

Declaration code

[Mapper]
public partial class Mapper
{
    [MapDerivedType<DerivedDto, Derived>]
    public partial Base Map(BaseDto src, int number);
}


public abstract class Base(Guid id, int number)
{
    public Guid Id { get; } = id;
    public int Number { get; } = number;
}

public sealed class Derived(Guid id, int number) : Base(id, number);

public abstract class BaseDto(Guid id)
{
    public Guid Id { get; } = id;
}

public sealed class DerivedDto(Guid id) : BaseDto(id);

Actual relevant generated code
Note that I've stripped namespaces manually, it's not related to the issue.

See how it tries to use the number in MapToDerived but it does not actually pass it from the calling method and does not generate a relevant parameter in MapToDerived. If I remove int number from Map() I do get an analyzer error that it could not figure out which constructor to use

    public partial class Mapper
    {
        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.2.0.0")]
        public partial global::Base Map(global::BaseDto src, int number)
        {
            return src switch
            {
                global::DerivedDto x => MapToDerived(x),
                _ => throw new System.ArgumentException($"Cannot map {src.GetType()} to Base as there is no known derived type mapping", nameof(src)),
            };
        }

        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.2.0.0")]
        private global::Derived MapToDerived(global::DerivedDto source)
        {
            var target = new global::Derived(source.Id, number);
            return target;
        }
    }

Expected relevant generated code

    public partial class Mapper
    {
        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.2.0.0")]
        public partial global::Base Map(global::BaseDto src, int number)
        {
            return src switch
            {
                global::DerivedDto x => MapToDerived(x, number),
                _ => throw new System.ArgumentException($"Cannot map {src.GetType()} to Base as there is no known derived type mapping", nameof(src)),
            };
        }

        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.2.0.0")]
        private global::Derived MapToDerived(global::DerivedDto source, int number)
        {
            var target = new global::Derived(source.Id, number);
            return target;
        }
    }

Environment (please complete the following information):

  • Mapperly Version: 4.2.0
  • Nullable reference types: enabled
  • .NET Version: .NET 9.0.101
  • Target Framework: .net8.0
  • Compiler Version: 4.12.0-3.24570.6 (913fb4ec)
  • C# Language Version: 12.0
  • IDE: Rider 2024.3.3
  • OS: Windows 22H2

Additional context
The real life context is as follows. I have an ordered array of polymorphic items that have some props. Since relational DBs can't preserve the order, I need to convert it to an array of "DB-ready" items which differ in that they have a number representing their position in the array so it can be later reconstructed in the same order.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions