Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使AutoMapper不缓存映射对象?_C#_.net_Automapper - Fatal编程技术网

C# 如何使AutoMapper不缓存映射对象?

C# 如何使AutoMapper不缓存映射对象?,c#,.net,automapper,C#,.net,Automapper,当AutoMapper遇到已经映射的对象时,它似乎会再次使用该对象,而不是尝试重新映射它。我相信它是基于.Equals()实现的 我有一棵正在绘制的树。因此,一个具有一些属性和子节点的节点。多个节点具有相同的值.Equals(),因为它基于Id属性。节点的子节点不同,我需要重新映射这些子节点,但它使用缓存的映射值 有没有办法关闭缓存映射?我所能想到的就是实现一个新的转换器,但这完全违背了使用AutoMapper的目的 下面是一个关于如何复制的示例 void Main() { var so

当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();
    }
}
void Main()
{
var source=新列表
{
新标签
{ 
Id=1,
Name=“Tag 1”,
ChildTags=新列表
{
新标签
{ 
Id=2,
Name=“tag2”,
ChildTags=新列表
{
新标记{Id=3,Name=“Tag 3”},
新标记{Id=4,Name=“Tag 4”}
}
}
}
},
新标记{Id=1,Name=“Tag 1”},
新标签
{
Id=3,Name=“Tag 3”,ChildTags=新列表
{
新标记{Id=4,Name=“Tag 4”}
}
}
};
CreateMap();
var results=Mapper.Map(源);
结果:Dump();
}
公共类标签
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共IEnumerable子标签{get;set;}
公共覆盖布尔等于(对象对象对象)
{
if(obj==null)
{
返回false;
}
var x=这个;
变量y=(标记)obj;
返回x.Id等于(y.Id);
}
公共覆盖int GetHashCode()
{
返回Id.GetHashCode();
}
}
当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]

    }
公共类CustomerSource
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共日期时间出生日期{get;set;}
public int NumberOfOrders{get;set;}
}
公共类CustomerTarget
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共日期时间出生日期{get;set;}
public int NumberOfOrders{get;set;}
}
[测试方法]
公共无效测试_AutoMapper()
{
CreateMap();
var source=new CustomerSource(){DateOfBirth=DateTime.Now,FirstName=“FirstName”,LastName=“LastName”,NumberOfOrders=int.MaxValue};
var res1=Mapper.Map(源);
Console.WriteLine(res1.FirstName);//打印FirstName
source.FirstName+=“[更新]”;
source.LastName+=“[更新]”;
var res2=Mapper.Map(源);
Console.WriteLine(res1.FirstName);//打印FirstName[更新]
}
没有您的代码,很难进行更深入的研究。
还有一个方法Mapper.Reset()用于清除MapperEngine和MapingConfiguration(所有内部映射表达式都将丢失)

我也遇到了同样的问题。 当您两次映射同一对象时不会发生这种情况-当您有一个对象的树继承者时会发生这种情况,并且相同的值存在于树的两个位置(但具有不同的子值) 映射项的第二个实例时,它使用第一个实例的子值,而不是重新评估子值应该是什么

以下是我的例子:

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);
}
类标记{
int Id{get;set;}
字符串名称{get;set;}
IEnumerable ChildTags{get;set;}
}
公开无效测试()
{
var source=新列表
{
新标签{Id=1,Name=“Tag 1”,ChildTags=new List
{
新标签{Id=2,Name=“Tag 2”,ChildTags=new List
{
新标记{Id=3,Name=“Tag 3”},
新标记{Id=4,Name=“Tag 4”}
}
}
}
},
新标记{Id=1,Name=“Tag 1”},
新标签{
Id=3,Name=“Tag 3”,ChildTags=新列表
{
新标记{Id=4,Name=“Tag 4”}
}
}
};
Mapper.CreateMap()
.ForMember(dest=>dest.ChildTags,
opt=>opt.MapFrom(src=>src.ChildTags));
var result=Mapper.Map(标记);
}
结果

  • 标记1(即源代码[0])的第一个实例及其所有子项都是完美的

  • 标记1的第二个实例(即源代码[1])包含第一个实例的所有子项—它不应该包含任何子项

  • 标记3的第二个实例(即源代码[2])没有任何子项-它应该将标记4作为子项


您映射的树对象的Equals行为似乎不合适

仅当“指定的对象等于当前对象”时,该方法才应返回true -

在您的例子中,有两个树对象共享相同的id,但很明显,它们不是“相等”的,因为它们有不同的子对象

我建议看看为什么Equals方法被如此滥用,以及你是否可以这样做
Mapper.Reset();
Mapper.CreateMap<Tag, Tag>();
var results = Mapper.Map<IList<Tag>, IList<Tag>>(source, opt => opt.DisableCache = true);