当指定条件 != null 时,Automapper 未正确映射 null 列表成员
Automapper does not map properly null List member, when the condition != null is specified
当我尝试映射对象的空列表(成员)时出现问题,考虑到我指定:
.ForAllMembers(opts => opts.Condition((src, dest, srcMember) =>
srcMember != null
));
cfg.AllowNullCollections = true; // didn't help also
代码中的简短示例:
gi.PersonList = new List<Person>();
gi.PersonList.Add(new Person { Num = 1, Name = "John", Surname = "Scott" });
GeneralInfo gi2 = new GeneralInfo();
gi2.Qty = 3;
Mapper.Map<GeneralInfo, GeneralInfo>(gi2, gi);
gi.PersonList.Count = 0
,如何解决?
using System;
using System.Collections.Generic;
using AutoMapper;
public class Program
{
public static void Main(string[] args)
{
Mapper.Initialize(cfg =>
{
cfg.AllowNullCollections = true;
cfg.CreateMap<GeneralInfo, GeneralInfo>()
.ForAllMembers(opts => opts.Condition((src, dest, srcMember) =>
srcMember != null
));
});
GeneralInfo gi = new GeneralInfo();
gi.Descr = "Test";
gi.Dt = DateTime.Now;
gi.Qty = 1;
gi.PersonList = new List<Person>();
gi.PersonList.Add(new Person { Num = 1, Name = "John", Surname = "Scott" });
GeneralInfo gi2 = new GeneralInfo();
gi2.Qty = 3;
Console.WriteLine("Count antes de mapeo = " + gi.PersonList.Count);
Mapper.Map<GeneralInfo, GeneralInfo>(gi2, gi);
Console.WriteLine("Count despues de mapeo = " + gi.PersonList.Count);
// Error : gi.PersonList.Count == 0 !!!!
//por que? si arriba esta: Condition((src, dest, srcMember) => srcMember != null ...
}
}
class Person
{
public int Num { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
class GeneralInfo
{
public int? Qty { get; set; }
public DateTime? Dt { get; set; }
public string Descr { get; set; }
public List<Person> PersonList { get; set; }
}
这样试试;
gi = Mapper.Map<GeneralInfo, GeneralInfo>(gi2);
我最近遇到了这个问题,如果目标和源的类型相同,目标参数无法按预期工作。
此外,我想通知您它与 Collection
个对象无关。如果调试 gi
对象,您将看到其他属性也保留旧值。如果您将目标实例作为目标参数传递,Automapper
不会更改之前分配的 属性 值。我认为,Automapper
不是为创建 copy/clone 个对象而设计的,这一点最重要。
这应该可行,但我不确定您是否想像这样进行微观管理:
cfg.AllowNullCollections = true;
cfg.CreateMap<GeneralInfo, GeneralInfo>()
.ForMember(x => x.PersonList, opts => opts.PreCondition((src) => src.PersonList != null));
问题是专门处理的集合(虽然 AutoMapper 在这种情况下有点奇怪,但它不是我最喜欢的,但对于大多数映射器来说都是如此)并且似乎需要初始化目标集合。如我所见,集合并未完整复制,这是有道理的,但您需要初始化并复制单个项目(这是我的推论,但听起来不错)。
即即使您跳过源,目标仍然会重新初始化(空)。
问题似乎是 Condition
,考虑到它们的 documentation,它在稍后的某个时间应用,此时目的地已经被初始化。
另一方面,PreCondition
有一个不同的签名,可以像您预期的那样使用,因为它不需要实际值,只有源可用。
唯一可行的解决方案是使用 "per member" PreCondition
(如上)。
编辑:
...或者这个(使用 ForAllMembers
),但有点难看,反射等
cfg.CreateMap<GeneralInfo, GeneralInfo>()
.ForAllMembers(opts =>
{
opts.PreCondition((src, context) =>
{
// we can do this as you have a mapping in between the same types and no special handling
// (i.e. destination member is the same as the source property)
var property = opts.DestinationMember as System.Reflection.PropertyInfo;
if (property == null) throw new InvalidOperationException();
var value = property.GetValue(src);
return value != null;
});
}
);
...但似乎没有对此提供更清晰的支持。
编辑(错误和最终想法):
Conditional mapping to existing collection doesn't work from version 5.2.0 #1918
正如评论中指出的那样(@LucianBargaoanu),这似乎确实是一个错误,因为它在 'corner' 案例中不一致(虽然我不同意这一点,但这是一个非常典型的场景)映射集合和传递目的地时。在这种情况下,它几乎使 Condition
无用,因为目的地已经是 initialized/cleared。
唯一的解决方案确实似乎是 PreCondition
(但由于签名不同,它有问题,我个人不确定为什么他们不传递相同的过多参数也进入前提条件?)。
这里还有更多信息:
nest collection is clear when using Condition but not Ignore #1940
Collection property on destination object is overwritten despite Condition() returning false #2111
Null source collection emptying destination collection #2031
当我尝试映射对象的空列表(成员)时出现问题,考虑到我指定:
.ForAllMembers(opts => opts.Condition((src, dest, srcMember) =>
srcMember != null
));
cfg.AllowNullCollections = true; // didn't help also
代码中的简短示例:
gi.PersonList = new List<Person>();
gi.PersonList.Add(new Person { Num = 1, Name = "John", Surname = "Scott" });
GeneralInfo gi2 = new GeneralInfo();
gi2.Qty = 3;
Mapper.Map<GeneralInfo, GeneralInfo>(gi2, gi);
gi.PersonList.Count = 0
,如何解决?
using System;
using System.Collections.Generic;
using AutoMapper;
public class Program
{
public static void Main(string[] args)
{
Mapper.Initialize(cfg =>
{
cfg.AllowNullCollections = true;
cfg.CreateMap<GeneralInfo, GeneralInfo>()
.ForAllMembers(opts => opts.Condition((src, dest, srcMember) =>
srcMember != null
));
});
GeneralInfo gi = new GeneralInfo();
gi.Descr = "Test";
gi.Dt = DateTime.Now;
gi.Qty = 1;
gi.PersonList = new List<Person>();
gi.PersonList.Add(new Person { Num = 1, Name = "John", Surname = "Scott" });
GeneralInfo gi2 = new GeneralInfo();
gi2.Qty = 3;
Console.WriteLine("Count antes de mapeo = " + gi.PersonList.Count);
Mapper.Map<GeneralInfo, GeneralInfo>(gi2, gi);
Console.WriteLine("Count despues de mapeo = " + gi.PersonList.Count);
// Error : gi.PersonList.Count == 0 !!!!
//por que? si arriba esta: Condition((src, dest, srcMember) => srcMember != null ...
}
}
class Person
{
public int Num { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
class GeneralInfo
{
public int? Qty { get; set; }
public DateTime? Dt { get; set; }
public string Descr { get; set; }
public List<Person> PersonList { get; set; }
}
这样试试;
gi = Mapper.Map<GeneralInfo, GeneralInfo>(gi2);
我最近遇到了这个问题,如果目标和源的类型相同,目标参数无法按预期工作。
此外,我想通知您它与 Collection
个对象无关。如果调试 gi
对象,您将看到其他属性也保留旧值。如果您将目标实例作为目标参数传递,Automapper
不会更改之前分配的 属性 值。我认为,Automapper
不是为创建 copy/clone 个对象而设计的,这一点最重要。
这应该可行,但我不确定您是否想像这样进行微观管理:
cfg.AllowNullCollections = true;
cfg.CreateMap<GeneralInfo, GeneralInfo>()
.ForMember(x => x.PersonList, opts => opts.PreCondition((src) => src.PersonList != null));
问题是专门处理的集合(虽然 AutoMapper 在这种情况下有点奇怪,但它不是我最喜欢的,但对于大多数映射器来说都是如此)并且似乎需要初始化目标集合。如我所见,集合并未完整复制,这是有道理的,但您需要初始化并复制单个项目(这是我的推论,但听起来不错)。
即即使您跳过源,目标仍然会重新初始化(空)。
问题似乎是 Condition
,考虑到它们的 documentation,它在稍后的某个时间应用,此时目的地已经被初始化。
PreCondition
有一个不同的签名,可以像您预期的那样使用,因为它不需要实际值,只有源可用。
唯一可行的解决方案是使用 "per member" PreCondition
(如上)。
编辑:
...或者这个(使用 ForAllMembers
),但有点难看,反射等
cfg.CreateMap<GeneralInfo, GeneralInfo>()
.ForAllMembers(opts =>
{
opts.PreCondition((src, context) =>
{
// we can do this as you have a mapping in between the same types and no special handling
// (i.e. destination member is the same as the source property)
var property = opts.DestinationMember as System.Reflection.PropertyInfo;
if (property == null) throw new InvalidOperationException();
var value = property.GetValue(src);
return value != null;
});
}
);
...但似乎没有对此提供更清晰的支持。
编辑(错误和最终想法):
Conditional mapping to existing collection doesn't work from version 5.2.0 #1918
正如评论中指出的那样(@LucianBargaoanu),这似乎确实是一个错误,因为它在 'corner' 案例中不一致(虽然我不同意这一点,但这是一个非常典型的场景)映射集合和传递目的地时。在这种情况下,它几乎使 Condition
无用,因为目的地已经是 initialized/cleared。
唯一的解决方案确实似乎是 PreCondition
(但由于签名不同,它有问题,我个人不确定为什么他们不传递相同的过多参数也进入前提条件?)。
这里还有更多信息:
nest collection is clear when using Condition but not Ignore #1940
Collection property on destination object is overwritten despite Condition() returning false #2111
Null source collection emptying destination collection #2031