Jorr.it
Jorr.it

Reputation: 1330

AutoMapper: How to MapFrom with string parameter when flattening

The MapFrom method of AutoMapper has two overloads:

.MapFrom(Expression<Func<object, object>>

and

.MapFrom<TMember>(string)

The first overload can be used like this:

.ForMember(dest => dest.Date, opt => opt.MapFrom(order => order.Customer.DateOfBirth))

I tried the second overload like this:

.ForMember(dest => dest.Date, opt => opt.MapFrom<DateTime>("Order.Customer.DateOfBirth"))

But it does not work when using a property of an association. Who nows how this second overload can be used when using flattening?

I ask this because I look for a way to do the mapping dynamically; for example:

.ForMember(dest => dest.Date, opt => opt.MapFrom<DateTime>(givenPropertyString))

Thanks in advance.

Upvotes: 4

Views: 4875

Answers (2)

Ilya Chumakov
Ilya Chumakov

Reputation: 25039

There are several options to map types dynamically using Automapper.

First of all, Automapper DynamicMap is supposed to use if the source type is unknown at compile time. It allows to specify only the destination type:

var message = Mapper.DynamicMap<ICreateOrderMessage>(order);

And about your question about MapFrom(string) - it works exaclty you suggest:

Mapper.CreateMap<UserModel, UserDto>()
    .ForMember(dto => dto.FullName, opt => opt.MapFrom<string>("FirstName"));

Probably nested properties like your "Order.Customer.DateOfBirth" just are not supported.

Upvotes: 2

Arghya C
Arghya C

Reputation: 10078

Seems like the MapFrom overload .MapFrom<TMember>(string) doesn't work well with nested properties (I might be wrong here). But, for your questions, you can create a custom method to get nested child property value using reflection. And use it to map any property value dynamically with string NestedPropertyName.

This is the custom method (source of method here)

public static object GetNestedPropertyValue(object obj, string nestedDottedPropertyName)
{
    foreach (String part in nestedDottedPropertyName.Split('.'))
    {
        if (obj == null)
            return null;

        PropertyInfo info = obj.GetType().GetProperty(part);
        if (info == null)
            return null;

        obj = info.GetValue(obj, null);
    }
    return obj;
}

And you can use this method in MapFrom dynamically (for any property), like this

.ForMember(dest => dest.Date, 
            opt => opt.MapFrom(src => GetNestedPropertyValue(src, "Order.Customer.DateOfBirth")));

Upvotes: 4

Related Questions