Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

automapper map interface to interface or object

How to map objects inherited from one interface to objects inherited from another interface.

I have such code structure

public interface IDataTranslatable
{
    List<DataTranslation> SpanishDataTranslations {get;set;}
}

public interface IDataTranslatableDto
{
    List<DataTranslationDto> DataTranslations { get; set; }
}

objects DataTranslation and DataTranslationDto have the same properties. I have many objects inherited from IDataTranslatable and IDataTranslatableDto interfaces. For example

public class Category : IDataTranslatable
{
    public string Name { get; set; }
    public ICollection<DataTranslation> SpanishDataTranslations { get; set; } = new List<DataTranslation>();
}

public class CategoryDto : IDataTranslatableDto
{
    public string Name { get; set; }
    public List<DataTranslationDto> DataTranslations { get; set; } = new List<DataTranslationDto>();
}

The best implementation for me would be something like that

config.CreateMap<IDataTranslatable, IDataTranslatableDto>()
.ForMember(dest => dest.DataTranslations, opts => opts.MapFrom(src => src.SpanishDataTranslations));

By this I mean that any object inherited from IDataTranslatable has to be mapped to object inherited IDataTranslatableDto to corresponding fields.

But this won't work, So I've tried to map like that

config.CreateMap<IDataTranslatable, CategoryDto>()
.ForMember(dest => dest.DataTranslations, opts => opts.MapFrom(src => src.SpanishDataTranslations));

Current using

public class AutoMapperConfiguration : IAutoMapperConfiguration
{
    public void Configure(IMapperConfigurationExpression config)
    {
        IDataTranslatableMappings(config);
    }

    private void IDataTranslatableMappings(IMapperConfigurationExpression config)
    {
        var mapCategory = config.CreateMap<Category, CategoryDto>().ForMember(dest => dest.DataTranslations, opts => opts.MapFrom(src => src.SpanishDataTranslations));
    }
}

This variant doesn't work as well. I've tried to explain my idea, how would be better to do it?

like image 243
ovasylenko Avatar asked Apr 28 '26 13:04

ovasylenko


1 Answers

You can configure it the following way:

Mapper.Initialize(config =>
{
    config.CreateMap<IDataTranslatable, IDataTranslatableDto>()
                .ForMember(x => x.DataTranslations, y => y.MapFrom(src => src.SpanishDataTranslations));
                
    config.CreateMap<Category, CategoryDto>()
                .IncludeBase<IDataTranslatable, IDataTranslatableDto>();                    

    config.CreateMap<DataTranslation, DataTranslationDto>();
});

And the usage of it:

var translation = new DataTranslation()
{
    Test = "Foo"
};

IDataTranslatable category = new Category()
{
     SpanishDataTranslations = new List<DataTranslation> { translation }
};

var result = Mapper.Map<IDataTranslatableDto>(category);

You will be forced to add every implementation of IDataTranslatable and IDataTranslatableDto to the mapping configuration.


Update

From version 8.0 and above, you can use IncludeDerived on your base type and therefore no longer need to explicitly declare all implementations of your interface.

like image 58
Dominik Avatar answered May 01 '26 03:05

Dominik