10

オブジェクトのリストをあるタイプから別のタイプにマッピングするとき、AutoMapper はキャッシュを使用していると思います。次のコードを見てください。

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; }
    }

}

コードの出力は、destList リストの最初のオブジェクトの SomeOtherNumber のみを設定したにもかかわらず、最初の 3 つの項目が同じオブジェクト参照を参照しているため、同じプロパティ値を持っていることを示しています。この動作を無効にできるかどうかを知りたいので、ソース リストに重複した参照があっても、宛先リストに重複した参照はありません。これは理にかなっていますか?

出力は次のとおりです。

SomeNumber: 10, SomeOtherNumber: 100
SomeNumber: 10, SomeOtherNumber: 100
SomeNumber: 10, SomeOtherNumber: 100
SomeNumber: 69, SomeOtherNumber: 0
4

1 に答える 1

5

当分の間、これは AutoMapper では実行できないと言えます。インスタンス キャッシングはかなり深く組み込まれており、現在のところ簡単にオフにすることはできません。あなたのユースケースは非常に奇妙ですが...リストに同じソースオブジェクトを複数回持っていますが、それでも異なる宛先オブジェクトが必要なのは、私の観点では非常に珍しいことです。

しかし、かなり悪いハックで回避できます。これは、インスタンス キャッシングをグローバルにオフにし、AutoMapper の実装の詳細に依存するため、慎重に使用してください。それでも試してみたい場合は、開発ブランチでのみ修正されるバグのため、以下のソリューションは Automapper 2.2.0 では機能しない ため、AutoMapper をソースからビルドするか、次のリリースを待つ必要があります。

それにもかかわらず、ここに詳細があります

インスタンスのキャッシュは、他のすべての実装と同様にプライベート クラスであるTypeMapObjectMapperRegistry.CacheMappingStrategy [source]によって処理されます。ITypeMapObjectMapper

ただし、TypeMapObjectMapperRegistry.AllMappersすべてを返す必要があるフィールドは、オーバーライド可能なITypeMapObjectMapperpublicです。Func

そのため、Mapper クラスを最初に使用する前に次のコードを追加します。

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

Mapper.CreateMap<Source, Destination>();
于 2013-01-22T20:08:00.867 に答える