Is your feature request related to a problem? Please describe.
I have an interface with many implementations.
I want to define one (user) mapping for all of them by doing something like:
public partial TheTarget GeneratedMapping (TheSource source);
private TheTargetType MyMapping (TheInterface source) => // some logic here
The issue is that on my source type (TheSource) the property is not typed as the interface, but as one of its implementations.
As such, the user mapping does not get picked up and one gets created instead.
Describe the solution you'd like
Currently, the object factory allows for generics with constraints. I think something like that for user mapping would work.
private TheTargetType MyMapping<T> (T source) where T : TheInterface => // some logic here
Describe alternatives you've considered
Currently, I name every single type that implements TheInterface and create a user mapping per type, but they all have the same exact logic.
Additional context
I have written some (failing) tests to more clearly demonstrate the problem, I hope it helps
[Fact]
public void SourceHasDerivedInterfaceTest()
{
var source = TestSourceBuilder.CSharp("""
using System;
using Riok.Mapperly.Abstractions;
public interface ITheInterface
{
long SomeProp { get; }
}
public class TheImpl : ITheInterface
{
public long SomeProp { get; set; }
}
public class TheOutsider
{
public long SomeProp { get; set; }
}
public class TheTarget
{
public TheOutsider Me { get; set; }
}
public class TheSource
{
public TheImpl Me { get; set; }
}
[Mapper]
public partial class TheMapper
{
public partial TheTarget TheMappingMethod(TheSource source);
private TheOutsider TheUserMapping(ITheInterface source) => source is null ? null : new TheOutsider();
}
""");
TestHelper.GenerateMapper(source)
.Should()
.HaveSingleMethodBody("var target = new global::TheTarget();\ntarget.Me = TheUserMapping(source.Me);\nreturn target;");
}
[Fact]
public void SourceHasDerived_ButUserMappingIsGeneric_InterfaceTest()
{
var source = TestSourceBuilder.CSharp("""
using System;
using Riok.Mapperly.Abstractions;
public interface ITheInterface
{
long SomeProp { get; }
}
public class TheImpl : ITheInterface
{
public long SomeProp { get; set; }
}
public class TheOutsider
{
public long SomeProp { get; set; }
}
public class TheTarget
{
public TheOutsider Me { get; set; }
}
public class TheSource
{
public TheImpl Me { get; set; }
}
[Mapper]
public partial class TheMapper
{
public partial TheTarget TheMappingMethod(TheSource source);
private TheOutsider TheUserMapping<T>(T source) where T : ITheInterface => source is null ? null : new TheOutsider();
}
""");
TestHelper.GenerateMapper(source)
.Should()
.HaveSingleMethodBody("var target = new global::TheTarget();\ntarget.Me = TheUserMapping(source.Me);\nreturn target;");
}
Is your feature request related to a problem? Please describe.
I have an interface with many implementations.
I want to define one (user) mapping for all of them by doing something like:
The issue is that on my source type (
TheSource) the property is not typed as the interface, but as one of its implementations.As such, the user mapping does not get picked up and one gets created instead.
Describe the solution you'd like
Currently, the object factory allows for generics with constraints. I think something like that for user mapping would work.
private TheTargetType MyMapping<T> (T source) where T : TheInterface => // some logic hereDescribe alternatives you've considered
Currently, I name every single type that implements
TheInterfaceand create a user mapping per type, but they all have the same exact logic.Additional context
I have written some (failing) tests to more clearly demonstrate the problem, I hope it helps