MapsterMapper / Mapster

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

Mapster.Tool Configure generated model to inherit class or Interface #564

Open furier opened 1 year ago

furier commented 1 year ago

Hi, the Mapster.Tool is great, but it would be even greater if one could configure AdaptAttributeBuilder such that types generated can inherit from a class without requiring the source class to inherit from it.

Base type

abstract class CreateDtoBase {
    Guid? Id { get; set; }
}

Config

void Register(CodeGenerationConfig config) 
{
    config
        .AdaptTo("Create[name]Dto")
        .ForType<MyEntity>()
        .WithBaseClass<CreateDtoBase>()
}

Generated output

class CreateMyEntityDto : CreateDtoBase {
    // other properties omitted for brevity
}

I am not sure what the best way to handle conflicting properties would be where both the inherited type and the type one generates from has a property with the same name but with different types. Maybe you could configure which property has precedence or simply throw an exception saying it is illegal.

Config examples

void Register(CodeGenerationConfig config) 
{
    config
        .AdaptTo("Create[name]Dto")
        .ForType<MyEntity>()
        .WithBaseClass<CreateDtoBase>(OnConflictingProperties.SelectInheritedProperty)

    config
        .AdaptTo("Update[name]Dto")
        .ForType<MyEntity>()
        .WithBaseClass<UpdateDtoBase>(OnConflictingProperties.SelectOriginalProperty)

    config
        .AdaptTo("[name]Dto")
        .ForType<MyEntity>()
        .WithBaseClass<UpdateDtoBase>(x => {
            x.OnConflict(y => y.Id, OnConflictingProperties.SelectOriginalProperty);
            x.OnConflict(y => y.Name, OnConflictingProperties.SelectInheritedProperty);
        })
}

The reason behind this requests is so that I can make generic services that expect T to inherit from some type in order for it to be viable as a parameter for one or more of its methods.

interface IMyGenericCrudService
{
    Task<IQueryable<TEntity>> CreateEntities<TEntity, TDto>(TDto[] dtos) where TDto : CreateDtoBase where TEntity : EntityBase;
    Task<IQueryable<TEntity>> UpdateEntities<TEntity, TDto>(TDto[] dtos) where TDto : UpdateDtoBase where TEntity : EntityBase;
}