【问题标题】:Let AutoMapper create destination objects only once and reuse them让 AutoMapper 只创建一次目标对象并重用它们
【发布时间】:2021-01-30 13:04:37
【问题描述】:

在以下示例控制台程序中,AutoMapper 生成 3 个 DestinationAuthor 对象,即使源层次结构仅使用 2 个不同的 SourceAuthor 对象(但其中一个对象两次)。

我正在寻找的是让 AutoMapper 为每个不同的源对象只生成一个不同的目标对象,然后在映射期间根据需要多次引用这个目标对象,而不是创建重复项。

结果将是一个对象层次结构,其中所有目标对象和引用完全模仿源层次结构中的对象。

using System.Diagnostics;
using System.Linq;
using AutoMapper;

namespace AutomapperMapOnce
{
    public class SourceBlog
    {
        public int BlogId { get; set; }
        public string Title { get; set; }
        public SourceAuthor Author { get; set; }
    }

    public class SourceAuthor
    {
        public int AuthorId { get; set; }
        public string Name { get; set; }
    }
    
    public class DestinationBlog
    {
        public int BlogId { get; set; }
        public string Title { get; set; }
        public DestinationAuthor Author { get; set; }
    }

    public class DestinationAuthor
    {
        public int AuthorId { get; set; }
        public string Name { get; set; }
    }

    internal static class Program
    {
        private static SourceBlog[] GetSourceBlogs()
        {
            var sourceAuthors = new[]
            {
                new SourceAuthor {AuthorId = 1, Name = "John"},
                new SourceAuthor {AuthorId = 2, Name = "Sam"}
            };

            var sourceBlogs = new[]
            {
                new SourceBlog
                {
                    BlogId = 1,
                    Title = "First Blog",
                    Author = sourceAuthors.First(a => a.Name == "John")
                },
                new SourceBlog
                {
                    BlogId = 2,
                    Title = "Second Blog",
                    Author = sourceAuthors.First(a => a.Name == "John")
                },
                new SourceBlog
                {
                    BlogId = 3,
                    Title = "Another Blog",
                    Author = sourceAuthors.First(a => a.Name == "Sam")
                }
            };

            Trace.Assert(sourceAuthors.Distinct().Count() == 2);
            Trace.Assert(sourceBlogs.Select(b => b.Author).Distinct().Count() == 2);
            
            return sourceBlogs;
        }

        private static void Main()
        {
            var mapper = new MapperConfiguration(
                cfg =>
                {
                    cfg.CreateMap<SourceBlog, DestinationBlog>();
                    cfg.CreateMap<SourceAuthor, DestinationAuthor>();
                }).CreateMapper();

            var sourceBlogs = GetSourceBlogs();
            var destinationBlogs = mapper.Map<DestinationBlog[]>(sourceBlogs);

            // Throws, because there are 3 distinct DestinationAuthor objects.
            Trace.Assert(destinationBlogs.Select(b => b.Author).Distinct().Count() == 2);
        }
    }
}

(我可能会以字典的形式设置某种对象存储,然后通过它手动解析实例,但这一定是一个非常常见的 AutoMapper 场景,所以我假设这个功能已经存在于核心或某些扩展中包。)

【问题讨论】:

    标签: c# .net-core automapper


    【解决方案1】:

    当然它是受支持的,而且非常简单。只需使用.PreserveReferences()(见5.0 Upgrade Guide: Circular references):

    var mapper = new MapperConfiguration(
        cfg =>
        {
            cfg.CreateMap<SourceBlog, DestinationBlog>()
                .PreserveReferences();
            cfg.CreateMap<SourceAuthor, DestinationAuthor>()
                .PreserveReferences();
        }).CreateMapper();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 2019-06-03
      • 2015-03-09
      • 1970-01-01
      • 2013-11-01
      • 1970-01-01
      相关资源
      最近更新 更多