【问题标题】:how to map an anonymous object to a class by AutoMapper?如何通过 AutoMapper 将匿名对象映射到类?
【发布时间】:2012-03-27 05:20:08
【问题描述】:

我有一个实体:

public class Tag {
    public int Id { get; set; }
    public string Word { get; set; }
    // other properties...
    // and a collection of blogposts:
    public ICollection<Post> Posts { get; set; }
}

还有一个模型:

public class TagModel {
    public int Id { get; set; }
    public string Word { get; set; }
    // other properties...
    // and a collection of blogposts:
    public int PostsCount { get; set; }
}

我这样查询实体(通过 EFNH):

var tagsAnon = _context.Tags
    .Select(t => new { Tag = t, PostsCount = t. Posts.Count() })
    .ToList();

现在,如何将tagsAnon(作为匿名对象)映射到TagModel 的集合(例如ICollection&lt;TagModel&gt;IEnumerable&lt;TagModel&gt;)?有可能吗?

【问题讨论】:

  • 为什么不将Tag 直接映射到TagModel?为什么是中间对象?
  • @AndrewWhitaker 因为 Entity Framework 只理解 Select 中的匿名类型,并且可以从中优化 SQL 查询。

标签: c# mapping automapper anonymous-types


【解决方案1】:

2019 年 7 月 31 日更新CreateMissingTypeMaps is now deprecated in AutoMapper v8, and will be removed in v9

9.0 版将移除对自动创建地图的支持。 您需要手动或使用显式配置地图 反思。也可以考虑attribute mapping


2016 年 5 月 11 日更新DynamicMap is now obsolete

现在您需要从将CreateMissingTypeMaps 设置为true 的配置创建映射器:

var tagsAnon = Tags
    .Select(t => new { t.Id, t.Word, PostsCount = t.Posts.Count })
    .ToList();

var config = new MapperConfiguration(cfg => cfg.CreateMissingTypeMaps = true);
var mapper = config.CreateMapper();

var tagsModel = tagsAnon.Select(mapper.Map<TagModel>)
    .ToList();

是的,这是可能的。对于您拥有的每个匿名对象,您必须使用 Automapper 的 Mapper 类的 DynamicMap&lt;T&gt; 方法。像这样的:

var tagsAnon = Tags
    .Select(t => new { t.Id, t.Word, PostsCount = t.Posts.Count() })
    .ToList();

var tagsModel = tagsAnon.Select(Mapper.DynamicMap<TagModel>)
    .ToList();

【讨论】:

  • 自 AutoMapper 4.1 起已弃用,现在该怎么办?
  • @MobileMon 我已经用新的方法更新了答案。感谢您指出。
  • 我可以确认使用“CreateMissingTypeMaps = true”的作品。此答案应标记为有效。谢谢!
  • CreateMissingTypeMaps = true 就像魅力一样。但是有没有为此创建通用函数的好方法?像“private static T MapDynamic(dynamic obj)”之类的东西。我做错了。有没有cmets?
  • CreateMissingTypeMaps = true 在 8.1.1.0 版本上也已弃用。我想现在最简单的方法是逐个字段映射。
【解决方案2】:

我不完全确定这是否可能。建议:

你为什么不能这样做:

var tagsAnon = _context.Tags
    .Select(t => new TagModel { Tag = t, PostsCount = t. Posts.Count() })
    .ToList();

这应该可以工作,但是它失败了(我已经读到 DynamicMap 在集合上是不确定的。

var destination = Mapper.DynamicMap<IEnumerable<TagModel>>(tagsAnon);

这证明 DynamicMap 确实适用于匿名类型,只是看起来不适用于枚举:

var destination = Mapper.DynamicMap<TagModel>(tagsAnon);

【讨论】:

    【解决方案3】:

    您可以使用最新的 Automapper 创建自定义函数来实现此目的。它使用上面其他答案中提到的CreateMissingTypeMaps 属性。

    public static List<T> MapDynamicList<T>(IEnumerable<object> obj)
        {
            var config = new MapperConfiguration(c => c.CreateMissingTypeMaps = true);
            var mapper = config.CreateMapper();
    
            var newModel = obj.Select(mapper.Map<T>).ToList();
    
            return newModel;
        }
    

    然后你只需用这行代码调用函数:

    var viewModel = Models.Helper.MapDynamicList<MatchSubCategory>(model);
    

    其中modelIEnumerable&lt;object&gt;List&lt;object&gt;

    【讨论】:

    • 每次创建一个新的映射器都会有成本。将映射器实例分配给私有静态变量通常会更好。
    猜你喜欢
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多