سؤال

I believe AutoMapper is using a cache when it is mapping lists of objects from one type to another. Take a look at the following code:

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Mapper.CreateMap<Source, Destination>()
                       .ForMember(dest => dest.SomeOtherNumber, opt => opt.Ignore());

            Mapper.AssertConfigurationIsValid();

            var sourceList = new List<Source>();

            var s1 = new Source {SomeNumber = 10};
            var s2 = new Source {SomeNumber = 69};

            sourceList.Add(s1);
            sourceList.Add(s1);
            sourceList.Add(s1);
            sourceList.Add(s2);

            var destList = Mapper.Map<List<Source>, List<Destination>>(sourceList);

            destList[0].SomeOtherNumber = 100;

            destList.ForEach(x => Console.WriteLine("SomeNumber: {0}, SomeOtherNumber: {1}", x.SomeNumber, x.SomeOtherNumber));
            Console.ReadLine();
        }
    }


    public class Source
    {
        public int SomeNumber { get; set; }
    }

    public class Destination
    {
        public int SomeNumber { get; set; }
        public int SomeOtherNumber { get; set; }
    }

}

The output of the code shows that even though I set only the SomeOtherNumber of the first object in the destList list, the first three items have the same property value because they are referencing the same object reference. I would like to know if I can disable this behavior, so even if I have duplicate references in the source list, I will not have duplicate references in the destination list. Does this make sense?

Here's the ouput:

SomeNumber: 10, SomeOtherNumber: 100
SomeNumber: 10, SomeOtherNumber: 100
SomeNumber: 10, SomeOtherNumber: 100
SomeNumber: 69, SomeOtherNumber: 0
هل كانت مفيدة؟

المحلول

I would say this is cannot be done with AutoMapper as the time being. The instance caching is built in pretty deep and currently it can't be turned off easily. Altough your use case is very strange... having the same source object multiple times in a list but you still want different destination objects is quite unusual in my point of view.

But it can be worked around with a pretty bad hack, because it will turn off instance caching globally and relies on the implementation details of AutoMapper so use it carefully. And if you still want to try it out the below mentioned solution is not working with Automapper 2.2.0 because of a bug which is only fixed in the development branch so you need to build AutoMapper from source or wait for the next release.

But nevertheless here are the details

The instance caching is handled by the TypeMapObjectMapperRegistry.CacheMappingStrategy [source] which like all the other ITypeMapObjectMapper implementation is a private class.

However the TypeMapObjectMapperRegistry.AllMappers field which should return all the ITypeMapObjectMapper is a public Func which can be overridden:

So add this code before the first usage of the Mapper class:

var baseMappers = TypeMapObjectMapperRegistry.AllMappers();
TypeMapObjectMapperRegistry.AllMappers = () => 
    baseMappers.Where(m => m.GetType().Name != "CacheMappingStrategy").ToArray();

Mapper.CreateMap<Source, Destination>();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top