在Auto Mapper中展平自引用对象 [英] Flatten self referencing object in Auto Mapper

查看:70
本文介绍了在Auto Mapper中展平自引用对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自引用模型,我想将其转换为平面列表.该模型如下所示.

I have a self referencing model that I would like to convert to a flat list. The model looks like this.

public class Node
{
    public List<Node> Nodes { get; set; }

    public Person Person { get; set; }

    public Language Language { get; set; }
}

public class NodeDTO
{
    public PersonDTO Person { get; set; }

    public LanguageDTO Language { get; set; }
}

public class NodeListDTO
{
    public List<NodeDTO> Nodes { get; set; }
}

我希望将层次结构中的所有节点展平到我的DTO对象中的一个列表.使用Auto Mapper可以做到这一点.

I want all nodes in the hierarchy to be flattend to one single list in my DTO object. Is this possible with Auto Mapper.

我尝试使用自定义值解析器,但是我还没有弄清楚如何在值解析器中使用PersonDTO和LanguageDTO的映射.

I have tried to use a Custom Value resolver but I haven't figured out how to use the mappings for PersonDTO and LanguageDTO inside the value resolver.

推荐答案

首先,您将需要代码来展平节点层次结构. AutoMapper不会自动执行此操作.为此,我使用了以下扩展方法:

First of all, you will need code to flatten nodes hierarchy. AutoMapper will not do that automatically. I use following extension methods for that:

public static IEnumerable<T> Flatten<T>(this T root,
   Func<T, IEnumerable<T>> childrenSelector)
{
    if (!typeof(T).IsValueType && root == null)
        throw new ArgumentNullException(nameof(root));

    return Flatten(new[] { root }, childrenSelector);
}

public static IEnumerable<T> Flatten<T>(this IEnumerable<T> source,
    Func<T, IEnumerable<T>> childrenSelector)
{
    if (source == null)
        throw new ArgumentNullException(nameof(source));

    if (childrenSelector == null)
        throw new ArgumentNullException(nameof(childrenSelector));

    return FlattenIterator(source, childrenSelector);
}

private static IEnumerable<T> FlattenIterator<T>(this IEnumerable<T> source,
    Func<T, IEnumerable<T>> childrenSelector)
{
    if (source != null)
    {
        foreach (var item in source)
        {
            yield return item;
            var children = childrenSelector(item);
            if (children != null)
                foreach (var child in FlattenIterator(children, childrenSelector))
                    yield return child;
        }
    }
}

下一步-您需要告诉AutoMapper如何展平并将节点层次结构映射到列表

Next - you need to tell AutoMapper how to flatten and map nodes hierarchy to list

MapperConfiguration config = new MapperConfiguration(c =>
{
    c.CreateMap<Person, PersonDTO>();
    c.CreateMap<Language, LanguageDTO>();
    c.CreateMap<Node, NodeDTO>();
    c.CreateMap<Node, NodeListDTO>()
        .ForMember(d => d.Nodes, o => o.ResolveUsing(s => s.Flatten(n => n.Nodes)));
});

现在您可以简单地使用

var node = new Node {
    Person = new Person { Id = 1, Name = "Bob" },
    Language = new Language { Id = 10, Code = "en" },
    Nodes = new List<Node> {
            new Node {
            Person = new Person {  Id = 3, Name = "Mike"},
            Language = new Language {  Id = 11, Code = "es"},
            Nodes = new List<Node> {
                    new Node {
                    Person = new Person {  Id = 4, Name = "Alex"},
                    Language = new Language {  Id = 11, Code = "es"}
                }
            }
        },
        new Node {
            Person = new Person {  Id = 5, Name = "Serge"},
            Language = new Language {  Id = 12, Code = "by"}
        }
    }
};

var nodeListDTO = mapper.Map<NodeListDTO>(node);

结果:

{
  "Nodes": [
    {
      "Person": { "Id": 1, "Name": "Bob" },
      "Language": { "Id": 10, "Code": "en" }
    },
    {
      "Person": { "Id": 3, "Name": "Mike" },
      "Language": { "Id": 11, "Code": "es" }
    },
    {
      "Person": { "Id": 4, "Name": "Alex" },
      "Language": { "Id": 11, "Code": "es" }
    },
    {
      "Person": { "Id": 5, "Name": "Serge" },
      "Language": { "Id": 12, "Code": "by" }
    }
  ]
}

这篇关于在Auto Mapper中展平自引用对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆