如何在 AutoMapper 中映射通用结构类型

Posted

技术标签:

【中文标题】如何在 AutoMapper 中映射通用结构类型【英文标题】:How to map generic struct type in AutoMapper 【发布时间】:2021-08-18 13:04:22 【问题描述】:

我想将MyEntity 映射到MyModel。第一个是由无法修改的 ORM 生成器给出的。 当然 AutoMapper 不能在没有任何映射定义的情况下映射 Id<> -> long

public class MyEntity

  public Id<MyEntity> Id  get; set; 
  public string Name  get; set; 
  public Id<MyFooEntity> FooId  get; set; 
  public Id<MyBarEntity> BarId  get; set; 


public class MyModel

  public long Id  get; set; 
  public string Name  get; set; 
  public long FooId  get; set; 
  public long BarId  get; set; 


public struct Id<T>

  private long _internalId  get; set; 
  public long ToLong() => _internalId;

以下是有效的:

CreateMap<MyEntity, MyModel>()
  .ForMember(d.Id, o => o.MapFrom(s => s.ToLong())
  .ForMember(d.FooId, o => o.MapFrom(s => s.ToLong())
  .ForMember(d.BarId, o => o.MapFrom(s => s.ToLong());

我在一个实体中有很多实体和几十个 id 属性。我喜欢做的是定义一个通用结构映射Id&lt;&gt; -&gt; long。但这似乎是不可能的。我尝试了TypeConverterITypeConverter&lt;,&gt; 和其他东西。我得到的最接近的是这个,但后来 AutoMapper 抱怨 Id&lt;&gt; 不是引用类型,不能用作 System.Object

CreateMap(typeof(Id<>), long).ConvertUsing((s, d) => s.ToLong());

任何建议如何做到这一点?有没有办法定义像int -&gt; stringint -&gt; long、...等已经存在的全局映射?

【问题讨论】:

ConvertUsing(s =&gt;...) 【参考方案1】:

是的,这是可能的。但是你需要修改Id&lt;T&gt;结构体。

据我所知,您正在使用一些生成器来生成源文件。 MyEntity 例如。 生成类后需要手动修改Id&lt;T&gt; struct。例如,它应该有一个这样的界面:

public interface IId

    long ToLong();


public struct Id<T> : IId

    private long _internalId  get; set; 
    public long ToLong() => _internalId;

现在您可以像这样创建配置,它将映射类中的所有Id&lt;T&gt; 类型。

configuration.CreateMap<MyEntity, MyModel>();

configuration.CreateMap<IId, long>()
                .ConvertUsing(x => x.ToLong());

【讨论】:

吹毛求疵。 x 应该是 sources 是的,这样更好

以上是关于如何在 AutoMapper 中映射通用结构类型的主要内容,如果未能解决你的问题,请参考以下文章

AutoMapper用法

使用链接地图/传递映射/链式地图的 AutoMapper 地图

Automapper:不同类型之间的映射

如何使用automapper映射与多个表的数据集

如何在 Automapper 中映射匿名对象

09.AutoMapper 之自定义类型转换器(Custom Type Converters)