30

I am reading AutoMapper's ReverseMap() and I can not understand the difference between ForMember() and ForPath(). Implementations was described here. In my experience I achieved with ForMember().

See the following code where I have configured reverse mapping:

public class Customer
{
    public string Surname { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}
public class CustomerDto
{
    public string CustomerName { get; set; }
    public int Age { get; set; }
}

static void Main(string[] args)
{
    Mapper.Initialize(cfg =>
    {
        cfg.CreateMap<Customer, CustomerDto>()
           .ForMember(dist => dist.CustomerName, opt => opt.MapFrom(src => $"{src.Surname} {src.Name}"))
            .ReverseMap()
            .ForMember(dist => dist.Surname, opt => opt.MapFrom(src => src.CustomerName.Split(' ')[0]))
            .ForMember(dist => dist.Name, opt => opt.MapFrom(src => src.CustomerName.Split(' ')[1]));
    });

    // mapping Customer -> CustomerDto            
    //... 
    //

    // mapping CustomerDto -> Customer
    var customerDto = new CustomerDto
    {
        CustomerName = "Shakhabov Adam",
        Age = 31
    };
    var newCustomer = Mapper.Map<CustomerDto, Customer>(customerDto);
}

It is working.


Question

Do ForMember and ForPath the same things or when should I use ForPath() over ForMember()?

3
  • 3
    Apparently Member means (and accepts) direct property/field accessor, while Path - well, property/field path, i.e. property/field of a nested member.
    – Ivan Stoev
    Commented Aug 5, 2017 at 17:17
  • 1
    @IvanStoev, why .ForPath(dist => dist.Surname, opt => opt.MapFrom(src => src.CustomerName.Split(' ')[0])) and .ForMember(dist => dist.Surname, opt => opt.MapFrom(src => src.CustomerName.Split(' ')[0])) have same result? Commented Aug 5, 2017 at 17:25
  • 4
    Probably because path is a superset of member. So path can be used in any place which expects member, but not (always) vice versa. In your example there is no nested object property, so both are one and the same. But if you have something like Customer.Order.Name, you can use ForPath and not ForMember.
    – Ivan Stoev
    Commented Aug 5, 2017 at 17:57

2 Answers 2

7

In this case, to avoid inconsistencies, ForPath is translated internally to ForMember. Although what @IvanStoev says makes sense, another way to look at it is that ForPath is a subset of ForMember. Because you can do more things in ForMember. So when you have a member, use ForMember and when you have a path, use ForPath :)

4
  • This answer seems to state the opposite of what the docs suggest. What additional functionality is there in the ForMember as opposed to ForPath? I believe those are fundamentally the same, except the latter gets deeper into nested properties. It's mentioned on their website that about 5% of cases are the complicated ones. Commented Jul 3, 2023 at 11:09
  • It does no such thing :) Check the number of methods in the respective interfaces, there are a lot more with ForMember. Commented Jul 3, 2023 at 12:06
  • Sorry, my bad for formulating unclear statement. They have similar outcome of the operation. As it seems in practical case, when one runs the code, the outcome of them is the same, except one gets an exception for sub-properties when applying member-version, which works using path-version. The code itself, I haven't looked at so I'll simply accept your statement at the face value. But do you say that the functionality of the path-version is a subset of member-version, then, or the opposite? Commented Jul 3, 2023 at 17:37
  • 1
    As intellisense shows, you can do more things in ForMember. But if you don't need any of that, ForPath will do. Commented Jul 3, 2023 at 17:41
6

ForMember() can only access root-properties of the mapped object. ForPath() can also access its sub-properties.

In my experience they do the same thing with the one exception. If you have something like this:

a.CreateMap<Source, Destination>()
  .ForMember(
    a => a.RootProp.SubProp, 
    b => b.MapFrom(c => c.RootProp.Get()))

it's going to fail producing the following error.

System.ArgumentException: 'Expression 'a => a.RootProp.SubProp' must resolve to top-level member and not any child object's properties. You can use ForPath, a custom resolver on the child type or the AfterMap option instead. (Parameter 'lambdaExpression')'

Because of that you need to replace ForMember() with ForPath() like so.

a.CreateMap<Source, Destination>()
  .ForPath(
    a => a.RootProp.SubProp, 
    b => b.MapFrom(c => c.RootProp.Get()))

I have limited experience using AutoMapper but it tells me that ForPath() has the same funcionallity as ForMember() (although with some extras). In usual cases we use ForMember() instead of ForPath(). I am not sure why, perhaps due to performance issues.

Not the answer you're looking for? Browse other questions tagged or ask your own question.