Roman Pushkin
Roman Pushkin

Reputation: 6079

Automapper, complex property and inheritance

I'm trying to get AutoMapper work and really stuck with a simple task. I have a complex type defined in User entity:

[ComplexType]
public class CustomerProfile
{
    public string       FirstName                { get; set; }
    public string       LastName                 { get; set; }
    // ...
}

public class User
{
    public long Id {get; set;}
    public string Email { get; get; }
    public CustomerProfile CustomerProfile { get; set; }
}

And I have view model like that:

public class CustomerViewModel : CustomerProfile
{
    public string Email { get; set; }
}

So I just have all of the CustomerProfile properties in view model plus Email.

I want to map User to CustomerViewModel. I tried everything but didn't succeed actually. Even this code doesn't work:

Mapper.CreateMap<CustomerProfile, CustomerViewModel>();

Automapper just refuses to map anything.

How it could be mapped? Thanks.

Upvotes: 2

Views: 381

Answers (1)

Andrew Whitaker
Andrew Whitaker

Reputation: 126042

You can use .ConstructUsing to create a CustomerViewModel from a User instance. Then the remaining properties (e.g., Email) will be mapped automatically by AutoMapper as long as the names match:

Mapper.CreateMap<CustomerProfile, CustomerViewModel>();

Mapper.CreateMap<User, CustomerViewModel>()
    .ConstructUsing(src => Mapper.Map<CustomerViewModel>(src.CustomerProfile));

Example: https://dotnetfiddle.net/RzpD4z


Update

To make AssertConfigurationIsValid() pass, you need to ignore the properties that you've mapped manually. You also need to ignore the Email property on CustomerViewModel from the CustomerProfileCustomerViewModel mapping, since that will be taken care of by the UserCustomerViewModel mapping:

Mapper.CreateMap<CustomerProfile, CustomerViewModel>()
    // Ignore Email since it's mapped by the User to CustomerViewModel mapping.
    .ForMember(dest => dest.Email, opt => opt.Ignore());

Mapper.CreateMap<User, CustomerViewModel>()
    .ConstructUsing(src => Mapper.Map<CustomerViewModel>(src.CustomerProfile))
    // Ignore FirstName/LastName since they're mapped above using ConstructUsing.
    .ForMember(dest => dest.FirstName, opt => opt.Ignore())
    .ForMember(dest => dest.LastName, opt => opt.Ignore());

Updated example: https://dotnetfiddle.net/KitDiC

Upvotes: 2

Related Questions