Extra mapper parameters do not work with MapDerivedType
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.
This is not yet supported by Mapperly. Feel free to provide a PR 😊 A good starting point to contribute is the contributors documentation. Let us know if you plan to work on this 😊
rel. https://github.com/riok/mapperly/issues/1472
@latonz I suppose I could try looking into this but I unfortunately lack any significant experience in writing source generators and my assumption is that Mapperly is a rather steep entry point.
Could you please roughly estimate how difficult implementing this would be?
This is definitely not the easiest task to get started with source generators. Good first issues are labeled: good first issues. There are a couple good resources to get started with source generators, e.g. here.
Until supported I think it would be lovely to mention this among other things on the documentation page here: https://mapperly.riok.app/docs/configuration/additional-mapping-parameters/
Added a hint to the docs: https://github.com/riok/mapperly/pull/1893