24

AutoMapper が既にマップされているオブジェクトに遭遇すると、再マップを試みる代わりに、そのオブジェクトを再度使用するように見えます。に基づいてこれを行うと思います.Equals()

マップされているツリーがあります。したがって、いくつかのプロパティと子を持つノードです。.Equals()Id プロパティに基づいているため、複数のノードが の同じ値を持っています。ノードの子は異なり、それらを再マップする必要がありますが、キャッシュされたマップ値を使用しています。

キャッシュされたマッピングをオフにする方法はありますか? 私が考えることができるのは、新しいコンバーターを実装することだけですが、それは AutoMapper を使用する目的を完全に無効にします。

再現方法の例を次に示します。

void Main()
{
    var source = new List<Tag>
    {
        new Tag 
        { 
            Id = 1, 
            Name = "Tag 1", 
            ChildTags = new List<Tag>
            {
                new Tag 
                { 
                    Id = 2, 
                    Name = "Tag 2", 
                    ChildTags = new List<Tag> 
                    {
                        new Tag {Id = 3, Name = "Tag 3"},
                        new Tag {Id = 4, Name = "Tag 4"}
                    }
                }
            }
        },
        new Tag { Id = 1, Name = "Tag 1" },
        new Tag 
        {
            Id = 3, Name = "Tag 3", ChildTags = new List<Tag>
            {
                new Tag {Id = 4, Name = "Tag 4"}
            }
        }
    };

    Mapper.CreateMap<Tag, Tag>();
    var results = Mapper.Map<IList<Tag>, IList<Tag>>(source);

    results.Dump();
}

public class Tag
{
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<Tag> ChildTags { get; set; }

    public override bool Equals(Object obj)
    {
        if (obj == null)
        {
            return false;
        }

        var x = this;
        var y = (Tag)obj;

        return x.Id.Equals(y.Id);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}
4

5 に答える 5

10

キャッシュを無効にするオプションが追加されました。

Mapper.CreateMap<Tag, Tag>();
var results = Mapper.Map<IList<Tag>, IList<Tag>>(source, opt => opt.DisableCache = true);
于 2015-03-23T16:05:58.243 に答える
9

私はマッパーで同じ問題に直面しました。周りを見回すと、追加することで解決策が見つかりました

Mapper.Reset();

出典ブログ(訂正URL)

于 2013-01-15T08:30:07.507 に答える
4

私も同じ問題を抱えています。同じオブジェクトを 2 回マップする場合は発生しません。オブジェクトのツリー階層があり、ツリーの 2 つの場所に同じ値が存在する場合に発生します (ただし、子の値は異なります)。項目の 2 番目のインスタンスをマップする場合- 子の値がどうあるべきかを再評価する代わりに、最初のインスタンスの子の値を使用します。

これが私の例です:

class Tag { 
  int Id {get; set;}
  string Name {get; set;}
  IEnumerable<Tag> ChildTags  {get; set;}
}

public void Test()
{
var source =  new List<Tag>
            {
                new Tag { Id = 1, Name = "Tag 1", ChildTags = new List<Tag>
                            {
                                new Tag { Id = 2, Name = "Tag 2", ChildTags = new List<Tag> 
                                            {
                                                new Tag {Id = 3, Name = "Tag 3"},
                                                new Tag {Id = 4, Name = "Tag 4"}
                                            }
                                    }
                            }
                    },
                new Tag { Id = 1, Name = "Tag 1" },
                new Tag {
                        Id = 3, Name = "Tag 3", ChildTags = new List<Tag>
                            {
                                new Tag {Id = 4, Name = "Tag 4"}
                            }
                    }
            };

Mapper.CreateMap<Tag, Tag>()
    .ForMember(dest => dest.ChildTags,
        opt => opt.MapFrom(src => src.ChildTags));
var result = Mapper.Map<IList<Tag>, IList<Tag>>(tags);
}

その結果、

  • タグ 1 の最初のインスタンス (つまり、source[0]) とそのすべての子は完全です

  • タグ 1 の 2 番目のインスタンス (つまり、source[1]) には、最初のインスタンスのすべての子が含まれます。子は含まれません。

  • タグ 3 の 2 番目のインスタンス (つまり、source[2]) には子がありません。子としてタグ 4 が必要です。

于 2012-09-28T09:18:57.457 に答える
1

AutoMapper が既にマップされているオブジェクトに遭遇すると、再マップを試みる代わりに、そのオブジェクトを再度使用するように見えます。.Equals() に基づいてこれを行うと思います

なぜ、いつそれを見たのか説明できますか?

ソース コードをざっと見てみると、オブジェクトのキャッシュがないことがわかりました。これを説明するテストを次に示します。

   public class CustomerSource
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }

        public int NumberOfOrders { get; set; }
    }

    public class CustomerTarget
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }

        public int NumberOfOrders { get; set; }
    }

    [TestMethod]
    public void Test_AutoMapper()
    {
        Mapper.CreateMap<CustomerSource, CustomerTarget>();

        var source = new CustomerSource() { DateOfBirth = DateTime.Now, FirstName = "FirstName", LastName = "LastName", NumberOfOrders = int.MaxValue };

        var res1 = Mapper.Map<CustomerSource, CustomerTarget>(source);
        Console.WriteLine(res1.FirstName); // PRINT FirstName

        source.FirstName += "[UPDATED]";
        source.LastName += "[UPDATED]";

        var res2 = Mapper.Map<CustomerSource, CustomerTarget>(source);
        Console.WriteLine(res1.FirstName); // PRINT FirstName[UPDATED]

    }

コードがなければ、さらに深く掘り下げることは困難です。MapperEngine と MapingConfiguration をクリアする Mapper.Reset() メソッドもあります (すべての内部マッピング式が失われます)。

于 2012-09-20T08:19:08.127 に答える
0

マッピングしているツリー オブジェクトの Equals 動作が不適切なようです。

このメソッドは、「指定されたオブジェクトが現在のオブジェクトと等しい」場合にのみ true を返す必要があります。- http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

あなたの場合、同じIDを共有する2つのツリーオブジェクトがありますが、明らかに、それらは異なる子を持つため、「等しく」ありません。

Equals メソッドがこのように悪用された理由と、Equals メソッドをオーバーライドせずに別のメソッドを使用してツリー ID フィールドをより適切な名前でチェックすることで、必要な動作が得られるかどうかを確認することをお勧めします。TreeIdsAreEqual。

于 2012-10-12T14:43:14.407 に答える