Але*_*кий 5 c# automapper mapper automapper-6
当我尝试映射对象的空列表(成员)时出现问题,考虑到我指定:
.ForAllMembers(opts => opts.Condition((src, dest, srcMember) =>
srcMember != null
));
cfg.AllowNullCollections = true; // didn't help also
Run Code Online (Sandbox Code Playgroud)
代码中的简短示例:
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);
Run Code Online (Sandbox Code Playgroud)
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; }
}
Run Code Online (Sandbox Code Playgroud)
这应该工作,但我不确定你是否想要像这样微观管理它:
cfg.AllowNullCollections = true;
cfg.CreateMap<GeneralInfo, GeneralInfo>()
.ForMember(x => x.PersonList, opts => opts.PreCondition((src) => src.PersonList != null));
Run Code Online (Sandbox Code Playgroud)
问题是专门处理的集合(对于大多数映射器来说都是如此,虽然AutoMapper在这种情况下有点奇怪,但它不是我最喜欢的)并且似乎需要初始化目标集合.正如我所看到的,集合不是完全复制的,但是你需要初始化和复制单个项目(这是我的演绎,但听起来不错).
即使你跳过源,目的地仍然会重新初始化(空).
问题似乎是Condition,鉴于他们的文档,在稍后的某个时候应用,此时目的地已经初始化.
PreCondition 另一方面,有一个不同的签名可以像你想象的那样使用,因为它没有实际值,只有源可用.
似乎有效的唯一解决方案是使用"每个成员" 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;
});
}
);
Run Code Online (Sandbox Code Playgroud)
......但似乎没有任何更清洁的支持.
编辑(BUG&FINAL THOUGHTS):
正如评论中指出的那样(@LucianBargaoanu),这似乎是一个真正的错误,因为它在这个"角落"的情况下是不一致的(虽然我不同意这一点,这是一个非常典型的场景),当映射集合和传递时目的地.Condition在这种情况下,它几乎使得无用,因为目标已经初始化/清除.
确实唯一的解决方案似乎是PreCondition(但鉴于不同的签名,它有问题,我个人不确定为什么他们也没有将同样多的参数传递到PreCondition中?).
还有一些信息:
使用Condition但不忽略#1940时,nest collection是清晰的
尽管Condition()返回false#2111,目标对象上的Collection属性也会被覆盖
| 归档时间: |
|
| 查看次数: |
973 次 |
| 最近记录: |