Blowa
Blowa

Reputation: 70

AutoMapper c# runtime mapping depending on an object property

I would like to know, how could I, with AutoMapper, Map one Dto to multiple entities.

Lemme explain.

I've got one Dto, with an enum to describe its type (to avoid having multiple dtos)

Depending on that enum (RelationType here), I would like to map it to the correct Model (Entity, what ever, it's another object that I use in database).

public class BCardDto : IMappedDto
{
    public long Id { get; set; }

    public BCardRelationType RelationType { get; set; }
    public long RelationId { get; set; }
}

Here are is my Model base:

public class BCardModel : IMappedDto
{
    public long Id { get; set; }
}

And here the derived model :

public class CardBCardModel : BCardModel
{
    // ormlite, ignore that
    [Reference]
    public CardModel Card { get; set; }

    [ForeignKey(typeof(CardModel), ForeignKeyName = "fk_bcard_card")]
    public long RelationId { get; set; }
}

How do I map my Dto to the correct Model depending on the enum i've given ? (I don't wanna use Mapper.Map everywhere but I wanna let mapper do the runtime mapping job)

Here is how I do it for the Model -> Dto

        cfg.CreateMap<CardBCardModel, BCardDto>()
            .ForMember(s => s.RelationType, expression => expression.UseValue(BCardRelationType.Card))
            .IncludeBase<BCardModel, BCardDto>();

Tell me if I do something wrong and explain me why please :)

Thanks by advance, Blowa.

Upvotes: 2

Views: 3809

Answers (2)

Tal Segal
Tal Segal

Reputation: 2835

Another way to do the mapping is by using dynamic:

public class PersonDto
{
    public string Name { get; set; }
}

public class StudentDto : PersonDto
{
    public int studentNumber { get; set; }
}

public class EmployeDto  : PersonDto
{
    public string EmployeId { get; set; }
}

public class Person
{
    public string Name { get; set; }
}

public class Student : Person
{
    public int StudentNumber { get; set; }
}

public class Employe : Person
{
    public string EmployeId { get; set; }
}

Create Map by using:

Mapper.CreateMap<StudentDto, Student>();
Mapper.CreateMap<EmployeDto, Employe>();

Do the Mapping by:

try
{
    var student = MapPerson((dynamic) studentDto);
    var employe = MapPerson((dynamic) employeDto);
}
catch
{
    throw new InvalidOperationException("Unknown ModelType...");
}

And define two Methods

public static Student MapPerson(StudentDto studentDto)
{
    return Mapper.Map<StudentDto, Student>(studentDto);
}

public static Employe MapPerson(EmployeDto employeDto)
{
    return Mapper.Map<EmployeDto, Employe>(employeDto);
}

The benefit is that you don't need a key and avoid the switch statement

Upvotes: 0

CodingYoshi
CodingYoshi

Reputation: 27009

Let's say you have a setup wherein there is a base class and 2 classes which derive the base class:

public class ModelBase
{
    public string Name { get; set; }
}

public class ModelOne : ModelBase { }

public class ModelTwo : ModelBase { }

Let's also say you have a DTO with an enum as below:

public class ModelDto
{
    public string Name { get; set; }
    public ModelType ModelType { get; set; }
}

public enum ModelType
{
    One = 1,
    Two = 2
}

So now the task is: How do I map the ModelDto to either ModelOne or ModelTwo depending on the value in ModelDto.ModelType property?

Here is how:

Mapper.Initialize(cfg => cfg.CreateMap<ModelDto, ModelBase>().ConstructUsing(x => 
{
    switch (x.ModelType)
    {
        case ModelType.One:
            return new ModelOne { Name = x.Name };
        case ModelType.Two:
            return new ModelTwo { Name = x.Name };
        default:
            throw new InvalidOperationException("Unknown ModelType...");
    }
}));

Usage

var dto1 = new ModelDto { ModelType = ModelType.One, Name = "ModelOne" };
var dto2 = new ModelDto { ModelType = ModelType.Two, Name = "ModelTwo" };

var one = Mapper.Map<ModelBase>(dto1);
var two = Mapper.Map<ModelBase>(dto2);

Upvotes: 3

Related Questions