ovasylenko
ovasylenko

Reputation: 2775

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?

Upvotes: 3

Views: 3713

Answers (1)

Dominik
Dominik

Reputation: 1741

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.

Upvotes: 6

Related Questions