2

I have created a generic method for mapping between List. It was working fine up to AutoMapper Version 3.3.1. After Version 4.0.0 its not working

public class Helper<T> : List<T> where T : new()
{
    public void MapBetween(List<T> NewList, List<T> OldList)
    {
        try
        {
            foreach (var NewItem in NewList)
            {
                string PrimaryKey = NewItem.GetType().GetProperties().First(f => f.Name.ToLower() == typeof(T).Name.ToLower() + "id").GetValue(NewItem).ToString();
                var OldItem = OldList.Find(delegate(T p) { return p.GetType().GetProperties()[0].GetValue(p).Equals(PrimaryKey); });
                AutoMapper.Mapper.DynamicMap(NewItem, OldItem);//Mapping
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}

public class Ac
{
    public string AcId { get; set; }
    public string A { get; set; }
    public string B { get; set; }
}

public void ConvertList()
{
        List<Ac> OldList = new List<Ac>();
        OldList.Add(new Ac { AcId = "1", A = "Old A", B = "Old B" });

        List<Ac> NewList = new List<Ac>();
        NewList.Add(new Ac { AcId = "1", A = "new A", B = "new B" });

        Helper<Ac> helper = new Helper<Ac>();
        helper.MapBetween(NewList, OldList);
}

Is there is any changes required in my approach?

Sascha
  • 10,231
  • 4
  • 41
  • 65
Avinash
  • 107
  • 1
  • 1
  • 7

1 Answers1

0

Since you are mapping to/from the same type, AutoMapper is using its AssignableMapper which simply assigns the value of the source object (an item in NewList) to the destination object (an item in OldList). Since Ac is a reference type but passed by value, when source is set to destination, the result never makes it back out to your destination object.

AutoMapper uses <SourceType>.IsAssignableFrom(<DestinationType>) when determining if AssignableMapper should be used and because the types are the same it uses it. (Potentially AutoMapper should check IsValueType as well when determining if it can be used).

Without more context, I'll take a stab at how to make this work to give you an idea. You could define a new type (e.g. AcNew) that inherits from the existing (Ac) and then use it for either NewList or OldList. For example, you could define a new type as:

public class AcNew : Ac {}

In ConvertList(), you would then use:

List<AcNew> NewList = new List<AcNew>();
NewList.Add(new AcNew { AcId = "1", A = "new A", B = "new B" });

When you do that, AutoMapper will no longer use AssignableMapper as assignment is not possible between base & derived types.

Regards,

Ross

Community
  • 1
  • 1
Ross Overstreet
  • 370
  • 1
  • 5