[英]How do I get AutoMapper to not cache mapped objects?
When AutoMapper encounters an object that's already been mapped, it seems to use that object again, instead of trying to re-map it. 当AutoMapper遇到已经映射的对象时,它似乎再次使用该对象,而不是尝试重新映射它。 I believe it does this based on .Equals()
. 我相信它基于.Equals()
来做到这一点。
I have a tree that's being mapped. 我有一棵正在映射的树。 So, a node with some properties, and children. 所以,一个具有一些属性的节点和子节点。 More than one of the nodes have the same value of .Equals()
, because it's based off an Id property. 不止一个节点具有相同的.Equals()
值,因为它基于Id属性。 The children of the nodes are different and I need those re-mapped, but it's using a cached map value. 节点的子节点是不同的,我需要重新映射,但它使用缓存的映射值。
Is there a way to turn the cached mapping off? 有没有办法关闭缓存的映射? All I can think of is implementing a new converter, but that totally defeats the purpose of using AutoMapper. 我能想到的只是实现一个新的转换器,但这完全违背了使用AutoMapper的目的。
Here is an example on how to reproduce. 这是一个如何重现的例子。
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();
}
}
There is now an option to disable the cache. 现在有一个禁用缓存的选项。
Mapper.CreateMap<Tag, Tag>();
var results = Mapper.Map<IList<Tag>, IList<Tag>>(source, opt => opt.DisableCache = true);
I've faced the same issue with the mapper, looking around i found that a solution for it, by adding 我遇到了与mapper相同的问题,环顾四周我找到了解决方案,通过添加
Mapper.Reset();
Source blog (corrected URL) 来源博客 (更正后的网址)
I also get the same issue. 我也遇到同样的问题。 It doesn't happen when you map the same object twice - it happens when you have a tree heirarcy of objects, and the same value exists in two places of the tree (but with different child values) When mapping the second instance of the item - it uses the child values of the first instance, instead of re-evaluating what the child values should be. 当您将相同的对象映射两次时不会发生这种情况 - 当您拥有对象的树层次时会发生这种情况,并且树的两个位置存在相同的值(但具有不同的子值)当映射项目的第二个实例时 - 它使用第一个实例的子值,而不是重新评估子值应该是什么。
Here is my example: 这是我的例子:
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);
}
In the result 在结果中
the first instance of Tag 1 (ie source[0]) and all of its children are perfect 标签1的第一个实例(即源[0])及其所有子项都是完美的
the second instance of Tag 1 (ie source[1]) has all the children of the first instance - it should not have any children 标签1的第二个实例(即源[1])具有第一个实例的所有子节点 - 它不应该有任何子节点
the second instance of Tag 3 (ie source[2]) does not have any children - it should have Tag 4 as a child 标签3的第二个实例(即源[2])没有任何孩子 - 它应该将标签4作为孩子
When AutoMapper encounters an object that's already been mapped, it seems to use that object again, instead of trying to re-map it. 当AutoMapper遇到已经映射的对象时,它似乎再次使用该对象,而不是尝试重新映射它。 I believe it does this based on .Equals() 我相信它基于.Equals()这样做
Can you explain why and when you see that ? 你能解释为什么以及何时看到这个?
After a quick look in the source code, I'm sure there is no cache for objects. 快速查看源代码后,我确信没有对象的缓存。 Here is a test that illustrate this : 这是一个测试,说明了这一点:
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]
}
Without your code, it is difficult to go more deeply. 没有你的代码,很难更深入。 There is also a method Mapper.Reset() that clears the MapperEngine and the MapingConfiguration (all internal mapping expressions will be lost) 还有一个方法Mapper.Reset()清除MapperEngine和MapingConfiguration(所有内部映射表达式都将丢失)
It seems that the Equals behaviour of the tree object you're mapping is inappropriate. 看来您映射的树对象的Equals行为是不合适的。
The method should only return true if "the specified object is equal to the current object." 如果“指定的对象等于当前对象”,则该方法应仅返回true。 - http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx - http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx
In your case, you have two tree objects sharing the same id but clearly, they are not "equal" since they have different children. 在您的情况下,您有两个共享相同ID的树对象但很明显,它们不是“相等”,因为它们有不同的子项。
I suggest looking at why the Equals method has been abused in this way and whether you could get the behaviour you need by not overriding the Equals method, instead using a different method to check the tree id field with a more appropriate name eg. 我建议看看为什么Equals方法以这种方式被滥用,以及你是否可以通过不覆盖Equals方法获得所需的行为,而是使用不同的方法来检查具有更合适名称的树id字段,例如。 TreeIdsAreEqual. TreeIdsAreEqual。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.