Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use AutoMapper with custom conversion on a specific property

Dear Internet community.

I need to map elements from one object to another. The classes are identical (same class name, same properties), so I figure we should give AutoMapper a try instead. It seems to work pretty well, but I've hit a snag: One class has an object type property that is used as sort of a 'wild-card' container.

public class MyPet
{
    public int Id { get; set; }
    public object Pet{ get; set; }
}

public class Cat
{

}

public class Dog
{

}

I intially figured that AutoMapper would be able to recognize the type of the instance and perform the appropriate mapping as instructed:

Mapper.CreateMap<LocalService.MyPet, ExternalService.MyPet>();
Mapper.CreateMap<LocalService.Cat, ExternalService.Cat>();
Mapper.CreateMap<LocalService.Dog, ExternalService.Dog>();


var dtoWithCat0 = new LocalService.MyPet()
{
    Id = 1,
    Item = new LocalService.Cat()
};

var dtoWithDog0 = new LocalService.MyPet()
{
    Id = 2,
    Item = new LocalService.Dog()
};

var dtoWithCat1 = Mapper.Map<ExternalService.MyPet>(dtoWithCat0);

var dtoWithDog1 = Mapper.Map<ExternalService.MyPet>(dtoWithDog0);

Console.WriteLine("{0}: {1} - {2}", dtoWithCat1.GetType().FullName, dtoWithCat1.Id, dtoWithCat1.Item.GetType().FullName);

Console.WriteLine("{0}: {1} - {2}", dtoWithCat1.GetType().FullName, dtoWithDog1.Id, dtoWithDog1.Item.GetType().FullName);

However, this is the output:

ExternalService.MyPet: 1 - LocalService.Cat
ExternalService.MyPet: 2 - LocalService.Dog

As you can see, AutoMapper is happy to copy the object reference of the property Item instead of creating a new ExternalService instance.

I'm looking for a way to instruct AutoMapper to resolve the Item property based on a custom function, something like this:

object ConvertPet(object source)
{
    if (source is LocalService.Cat) return Mapper.Map<ExternalService.Cat>(source as LocalService.Cat);
    if (source is LocalService.Dog) return Mapper.Map<ExternalService.Dog>(source as LocalService.Dog);
}

Any tips would be appreciated!

-S

PS. I notice that there exists a ConvertUsing method. Unfortunately, this appears to replace the "automatic" part of AutoMapper with an custom explicit mapping that needs to implement mapping of all properties on the DTO. I would like to be lazy and have AutoMapper make an exception just for that single property...

like image 330
Sigurd Garshol Avatar asked Feb 11 '23 09:02

Sigurd Garshol


1 Answers

May be MapFrom will help you

For Example

 Mapper.CreateMap<LocalService.MyPet, ExternalService.MyPet>()
            .ForMember(dest => dest.MyPet,
                        opt => opt.MapFrom(
                        src => ConvertPet(src.MyPet)));
like image 74
fly_ua Avatar answered Feb 16 '23 04:02

fly_ua