在 Automapper 中展平自引用对象

2024-01-11

我有一个自引用模型,我想将其转换为平面列表。模型看起来像这样。

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 对象中的一个列表。这可以通过自动映射器实现吗?

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


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

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 如何展平节点层次结构并将其映射到列表

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);

Result:

{
  "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" }
    }
  ]
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Automapper 中展平自引用对象 的相关文章

  • C++ 有像 Pascal 一样的“with”关键字吗?

    withPascal 中的关键字可用于快速访问记录的字段 有人知道 C 是否有类似的东西吗 前任 我有一个包含许多字段的指针 但我不想这样输入 if pointer gt field1 pointer gt field2 pointer g
  • 从 .Net 将简单数据插入 Excel 文件的最简单方法

    我有一个 Excel 文件 大约有 10 列和 1 20 行 我需要插入 1 20 行包含各种数据元素 我想知道是否有一种方法可以将一些标签放入 Excel 文件中 以便可以找到并替换它们 将列标记为 名称 的东西 这样我就可以在代码中说
  • 在 MVC 类上创建主键字段

    我是 MVC 和 C 新手 我只是偶然发现它并发现它很有趣 我遇到了一个不允许我继续的问题 这是我的代码 using System using System Collections Generic using System Linq usi
  • 浏览器收集哪些值作为回发数据?

    当页面被发送回服务器时 浏览器收集每个控件的当前值并将其粘贴到一个字符串中 然后 该回发数据通过 HTTP POST 发送回服务器 Q1 除了控件的 Text 属性和 SelectedIndexchanged 因此除了用户输入数据 之外 控
  • 如何在 C++ 的子目录中创建文件?

    这是我的代码 如何在子目录联系人中创建文件 每次创建该文件时 它都会出现在与我的程序相同的目录中 int main ofstream myfile contacts myfile open a myfile close 在构造函数中指定完整
  • 实体框架7审计日志

    我正在将一个旧项目移植到 ASP NET 5 和 Entity Framework 7 我使用数据库优先方法 DNX 脚手架 来创建模型 旧项目基于Entity Framework 4 审计跟踪是通过重写实现的SaveChanges的方法D
  • initializer_list 和默认构造函数重载决策

    include
  • 我们应该使用 Eval 还是 Databind 事件?

    当使用 Asp Net 并使用 ListView 等控件创建网站时 使用 Eval 命令是一个好习惯吗 还是应该在 databind 事件中填充文字和数据 取决于您是否想在更新事件上写回数据 在这种情况下数据绑定 如果您只想读取该数据 可以
  • ASP MVC 5 - 403 customError 不起作用

    我正在尝试为我的应用程序创建自定义错误页面 它在大部分情况下都有效 但不适用于403 errors 我的网络配置
  • 在非指针变量和类成员上放置 new

    考虑以下示例 include
  • 如何使用 C# 代码使用超链接的 onClick 事件?

    我正在尝试为页面中的超链接添加条件 而不是仅仅使用特定的链接 例如 a href help Tutorial html Tutorial a 我想为不同的用户显示不同的页面 例如 如果用户以管理员身份登录 他们将看到与普通用户不同的链接 我
  • AspNetCore.SignalR:无法启动未处于初始状态的连接

    我无法让 ASP NET Core SignalR 应用程序正常运行 我有这个服务器端代码 public class PopcornHub Hub private int Users public async Task BroadcastN
  • 使用 cudamalloc()。为什么是双指针?

    我目前正在浏览有关的教程示例http code google com p stanford cs193g sp2010 http code google com p stanford cs193g sp2010 学习CUDA 演示的代码 g
  • 打破条件变量死锁

    我遇到这样的情况 线程 1 正在等待条件变量 A 该变量应该由线程 2 唤醒 现在线程 2 正在等待条件变量 B 该变量应该由线程 1 唤醒 在我使用的场景中条件变量 我无法避免这样的死锁情况 我检测到循环 死锁 并终止死锁参与者的线程之一
  • .NET 的 HttpWebResponse 是否会自动解压缩 GZiped 和 Deflated 响应?

    我正在尝试执行一个接受压缩响应的请求 var request HttpWebRequest HttpWebRequest Create requestUri request Headers Add HttpRequestHeader Acc
  • 向每个收件人发送一封包含不同内容的电子邮件(使用抄送字段)

    在你因为这个问题 毫无意义 和 不可能 而驳回之前 请听我说完 问题 我们在使用我们的系统发送的每封电子邮件中实施跟踪像素 即具有唯一 URL 的可下载 GIF 文件 这有助于我们跟踪电子邮件的打开情况 问题是 当我们抄送一些收件人时 跟踪
  • C 中的静态和动态绑定(严格来说是 C,而不是 C++)是什么?

    我最初对发布这个问题感到担忧 以免它重复 但即使在谷歌搜索了许多关键字之后 我在 StackOverflow 上找不到任何解释 C 的静态和动态绑定的链接 尽管有 C 的问题和答案 但是都涉及classes以及显然不适合 C 的东西 Sta
  • 编译器什么时候内联函数?

    在 C 中 函数仅在显式声明时才内联inline 或在头文件中定义 或者编译器是否允许内联函数 因为他们认为合适 The inline关键字实际上只是告诉链接器 或告诉编译器告诉链接器 同一函数的多个相同定义不是错误 如果您想在标头中定义函
  • C# 中成员访问中的问号是什么意思?

    有人可以向我解释一下以下代码中会员访问中的问号是什么意思吗 它是标准 C 的一部分吗 尝试在 Xamarin Studio 中编译此文件时出现解析错误 this AnalyzerLoadFailed Invoke this new Anal
  • 如何获取通过网络驱动器访问的文件的 UNC 路径?

    我正在 VC 中开发一个应用程序 其中网络驱动器用于访问文件 驱动器由用户手动分配 然后在应用程序中选择驱动器 这会导致驱动器并不总是映射到相同的服务器 我该如何获取此类文件的 UNC 路径 这主要是为了识别目的 这是我用来将普通路径转换为

随机推荐