[英]AutoMapper mapping between enum and its integer values fails with ReverseMap
該應用程序是使用 DDD 方法構建的,具有一組單獨的持久性模型。 我調用了數據庫 object 或 dbo:
public class ParentDbo
{
public int ParentId { get; set; }
public int TypeId { get; set; }
}
public class ChildDbo
{
public int ChildId { get; set; }
public ParentDbo Parent { get; set; }
public int RetryNumber { get; set; }
}
我們有一個簡單的 model 來查看:父子關系。 RetryNumber
表示數據庫中的枚舉值。
在檢索數據時,它首先使用 Dapper 查詢數據庫,並使用它的splitOn
功能將 map 數據插入其中。 這部分無關緊要,但為了完整起見,我還是會展示它:
const string sql = "SELECT * FROM XXX ....";
using (var cnt = _dbConnectionFactory.CreateConnection())
{
var childDbos = await cnt.QueryAsync<ChildDbo, ParentDbo, ChildDbo>(
sql: sql,
map: (childDbo, parentDbo) =>
{
childDbo.Parent = parentDbo;
return childDbo;
},
splitOn: "ParentId"
);
}
Dapper 的局限性在於它不能將 map 數據傳輸到私有復雜對象。 這主要是我必須有兩套模型的原因。 我想使用私有設置器和其他技術將數據和邏輯封裝在域模型中。
這是我的域模型:
public class Parent
{
public int Id { get; private set; }
public int TypeId { get; private set; }
public Parent(int parentId, int typeId)
{
// Validations
this.Id = parentId;
this.TypeId = typeId;
}
}
public class Child
{
public int Id { get; private set; }
public Parent Parent { get; private set; }
public Attempt Attempt { get; private set; }
public Child(int childId, Parent parent, Attempt attempt)
{
// Validations
this.Id = childId;
this.Parent = parent;
this.Attempt = attempt;
}
}
對於域模型,我不想要公共設置器和無參數構造器。
Attempt
是帶有 integer 支持值的枚舉:
public enum Attempt
{
Original = 1,
FirstRetry = 2,
SecondRetry = 3,
LastRetry = 4
}
最后,我想在 Dbos 和域模型之間使用 AutoMapper 到 map。 這是映射:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Child, ChildDbo>()
.ForMember(dest => dest.ChildId, opts => opts.MapFrom(src => src.Id))
.ForMember(dest => dest.RetryNumber, opts => opts.MapFrom(src => (int)src.Attempt))
.ReverseMap();
CreateMap<Parent, ParentDbo>()
.ForMember(dest => dest.ParentId, opts => opts.MapFrom(src => src.Id))
.ReverseMap();
}
}
我想要雙向映射,所以我使用ReverseMap()
。
.Net Fiddle 演示: https://dotnetfiddle.net/saEHWd
它將域模型映射到 dbo 沒有問題:
但它的反向,從 dbo 到域模型的映射,正在拋出異常:
未處理的異常。 System.ArgumentException:Program+Child 需要有一個帶有 0 個參數或只有可選參數的構造函數。 AutoMapper.Mapper.MapCore[TSource,TDestination](TSource source, Tdestination destination, ResolutionContext context, Type sourceType, Type destinationType, IMemberMap memberMap) 中的 lambda_method18(Closure, Object, Child, ResolutionContext ) 中的(參數“類型”)。 Mapper.Map[TSource,Tdestination](TSource source, Tdestination destination) at AutoMapper.Mapper.Map[Tdestination](Object source) at Program.Main()
我試圖刪除枚舉屬性並且一切正常,所以我很確定這是有問題的枚舉映射。
據我在您的小提琴中看到的,您正在嘗試從ChildDbo
到Parent
的 map 並且沒有針對它的映射設置。 將映射代碼更改為:
var child2 = mapper.Map<Child>(childDbo);
由於第三個Child
的 ctor 參數和源屬性名稱不匹配,因此將 map 更改為:
CreateMap<Child, ChildDbo>()
.ForMember(dest => dest.ChildId, opts => opts.MapFrom(src => src.Id))
.ForMember(dest => dest.RetryNumber, opts => opts.MapFrom(src => (int)src.Attempt))
.ReverseMap()
.ConstructUsing((dbo, ctx) => new Child(dbo.ChildId, ctx.Mapper.Map<Parent>(dbo.Parent), (Attempt)dbo.RetryNumber));
看這里
或者將第三個Child
的 ctor 參數重命名為retryNumber
:
public Child(int childId, Parent parent, Attempt retryNumber)
看這里。
或使用ForCtorParam
:
CreateMap<Child, ChildDbo>()
.ForMember(dest => dest.ChildId, opts => opts.MapFrom(src => src.Id))
.ForMember(dest => dest.RetryNumber, opts => opts.MapFrom(src => (int)src.Attempt))
.ReverseMap()
.ForCtorParam("attempt", opt => opt.MapFrom(dbo => dbo.RetryNumber))
在這里。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.