MapsterMapper / Mapster

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

Interface mapping - Expressions for inherited classes #594

Open flobiber opened 1 year ago

flobiber commented 1 year ago

Hello,

i am trying to use mapster.tools for generating mappings between already existing objects.

In my playground project i have the following models:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Customer : Person
{
    public string WorkingPlace { get; set; }
}

public class PersonDto
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class CustomerDto : PersonDto
{
    public string WorkingPlace { get; set; }
}

And i have the following mapster IRegister config:

public class MappingRegister: IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        config.NewConfig<Person, PersonDto>()
            .Map( dto => dto.FirstName, entity => entity.LastName + "_MW")
            .Include<Customer, CustomerDto>();
    }
}

Then i define an interface that includes the mapping i want to generate:

[Mapper]
public interface IPersonMap
{
    PersonDto Map(Person person);

    Expression<Func<Person, PersonDto>> ProjectToDto { get; }

}

The generated output for PersonMap.Map() looks pretty good and is exactly what i want (includes type checking and mapping inherited objects).

But the result for PersonMap.ProjectToDto() looks only ok for "PersonDto" and ignores all inheritances. How can fix it to make Expressions also work for inheritance?

Bonus Question: Is there a way to mark Person & PersonDto as abstract?

jvmlet commented 1 year ago

And if you add Expression<Func<Person, CustomerDto >> CustomerToDto { get; } to the interface ?

flobiber commented 1 year ago

@jvmlet thank you for you response.

I adjust my interface to:

    Expression<Func<Person, PersonDto>> ProjectToDto { get; }

    Expression<Func<Person, CustomerDto>> ProjectToDto2 { get; }

The result looks like that:

        public Expression<Func<Person, PersonDto>> ProjectToDto => p1 => new PersonDto()
        {
            FirstName = p1.LastName + "_MW",
            LastName = p1.LastName
        };
        public Expression<Func<Person, CustomerDto>> ProjectToDto2 => p2 => new CustomerDto()
        {
            FirstName = p2.FirstName,
            LastName = p2.LastName
        };

So that also not help me.

jvmlet commented 1 year ago

Oh, you should be using Inherits

 config.ForType<X, A>()
.Map....

config.ForType<X, B>()
.Inherits<X, A>()
.Map...

class B :A{
}
flobiber commented 1 year ago

I think i am doing that the other way arround with that:

config.NewConfig<Person, PersonDto>()
    .Map( dto => dto.FirstName, entity => entity.LastName + "_MW")
    .Include<Customer, CustomerDto>();