如何使用自动映射器将子对象列表转换为字符串列表或 Guid 列表

How to use AutoMapper to convert Child Object list to either list of strings or list of Guids

提问人:Jon 提问时间:5/10/2022 最后编辑:Jon 更新时间:5/10/2022 访问量:587

问:

我尝试使用自定义转换

CreateMap<ChildB, string>().ConvertUsing(src => src.Name);

但是我有时会遇到这样的情况,有时我想得到上面的字符串,或者有时我只想得到Guid:CreateMap<ChildB, Guid>().ConvertUsing(src => src.Id);

它似乎会抛出并出错,因为它总是转换名称。对象是这样的:

public class ParentA
{
 public Guid Id {get;set;}
 public string Name {get;set;}
 public ICollection<ChildB>? {get;set;}
 ...
}

public class ChildB
{
 public Guid Id {get;set;}
 public string Name {get;set;}
 ...
}
public class ParentADTO1
{
 public Guid Id {get;set;}
 public string Name {get;set;}
 public ICollection<string> ChildNames{get;set;}
 ...
}
public class ParentADTO2
{
 public Guid Id {get;set;}
 public string Name {get;set;}
 public ICollection<Guid> ChildIds {get;set;}
 ...
}

所以问题是,我可以像这样使用这个函数吗?CreateMap

CreateMap<ParentA,ParentADTO1>()
  ...
 .ForMember(ent => ent.ChildNames, opt => opt.MapFrom(???))

CreateMap<ParentA,ParentADTO2>()
  ...
 .ForMember(ent => ent.ChildIds, opt => opt.MapFrom(???))

非常感谢您的帮助!!

谢谢 乔恩

C# entity-framework-core 自动映射器 嵌套列表

评论


答:

1赞 Markus 5/10/2022 #1

您可以像这样设置映射配置(我想该属性名为):Children

public class ParentA
{
 public Guid Id {get;set;}
 public string Name {get;set;}
 public ICollection<ChildB> Children {get;set;}
 // ...
}

CreateMap<ParentA,ParentADTO1>()
  // ...
 .ForMember(ent => ent.ChildNames, opt => opt.MapFrom(x => x.Children.Select(y => y.Name).ToArray()))

CreateMap<ParentA,ParentADTO2>()
  // ...
 .ForMember(ent => ent.ChildIds, opt => opt.MapFrom(x => x.Children.Select(y => y.Id).ToArray()))

评论

0赞 Jon 5/10/2022
嗯 - 太棒了!非常感谢您如此快速的回复
1赞 Sonny N 5/10/2022 #2

@Markus答案当然是有效的,并且是一个很好的解决方案。FWIW,这是您可以使用内置 AutoMapper 的 Flattening 模式的另一种方法。只需将 Get[PropertyName] 方法添加到源类中,即可以所需的任何方式组合子对象。以下是完整的示例:

public class Parent
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public ICollection<Child> Children { get; set; }

    public ICollection<string> GetChildNames()
    {
        return Children.Select(x => x.Name).ToArray();
    }

    public ICollection<Guid> GetChildIds()
    {
        return Children.Select(x => x.Id).ToArray();
    }
}

public class Child
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

public class ParentWithChildNames
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public ICollection<string> ChildNames { get; set; }
}
public class ParentWithChildIds
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public ICollection<Guid> ChildIds { get; set; }
}

//No need to map the member, you could use Get[PropertyName] approach to automatically map it
var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Parent, ParentWithChildIds>();
    cfg.CreateMap<Parent, ParentWithChildNames>();
});
var mapper = config.CreateMapper();

评论

0赞 Jon 5/10/2022
这很酷 - 因此 AutoMapper 知道由于 NamingConvention 应该使用“Get”函数来分配该字段。我假设两者都必须是 ICollection/IEnumerable 或其他任何内容才能使约定正常工作?
0赞 Sonny N 5/11/2022
是的,您的假设是正确的,“Get”方法的返回类型必须与属性类型兼容。