MapsterMapper / Mapster

A fast, fun and stimulating object to object Mapper
MIT License
4.38k stars 331 forks source link

Regression bug - works on 7.3.0 not on 7.4.0 #672

Open FaustoNascimento opened 9 months ago

FaustoNascimento commented 9 months ago

I found some pretty weird behaviour with Mapster 7.4.0...

Imagine you have the following DTOs:

public class Source
{
    public long Id { get; init; }
}

public class ADestination
{
    public int Id { get; init; }
}

public class BDestination : ADestination
{
    public new long Id { get; init; }
}

With no configuration at all, Mapster should be able to map between these two types and it can... but only depending on how it's invoked:

var source = new Source();
source.Adapt<BDestination>(); // this works
source.Adapt(new BDestination()); // this throws a AmbiguousMatchException exception

To make things worse ... if your DTOs are not as simple as this example and you use DI/IoC and you combine this with TypeAdapterConfig<Source, BDestination>.NewConfig().ConstructUsing() then the results are again unexpected depending on the Expression passed:

using Microsoft.Extensions.DependencyInjection;

var serviceProvider = new ServiceCollection().AddTransient<BDestination>().BuildServiceProvider();

// Obviously use *one* of the configurations below only

// Works if configured this way (only when doing Adapt<BDestination>() though!!)
TypeAdapterConfig<Source, BDestination>.NewConfig().ConstructUsing(_ => new BDestination());

// Does not work with this configuration - no matter what I try
TypeAdapterConfig<Source, BDestination>.NewConfig().ConstructUsing(_ => serviceProvider.GetRequiredService<BDestination>());

var source = new Source();
source.Adapt<BDestination>(); // Depending on configuration used, either Mapster will map successfully or throw AmbiguousMatchException  here

Any ideas what's going on and any potential workarounds?

FaustoNascimento commented 9 months ago

I've also tried it with DryIoC with the following registration:

var container = new Container();

container.Register<BDestination>();
TypeAdapterConfig<Source, BDestination>.NewConfig().ConstructUsing(_ => container.Resolve<BDestination>(IfUnresolved.Throw));

var source = new Source();
source.Adapt<BDestination>();

But this also fails with the same error - although I swear I had it working with DryIoC before...

FaustoNascimento commented 9 months ago

Ok cause I was really certain that this worked before with DryIoC and the only other thing I could think of was that I updated Mapster... I decided to go back to 7.3.0 and that works so this looks a regression bug?