按约定自动映射器定义,无需显式的CreateMap

时间:2019-05-20 12:54:04

标签: c# automapper

我正在尝试创建Automapper约定,以在带有下划线的大写属性的DTO与Pascal情况下的业务POCO之间进行映射。

我想不对每个类都显式调用CreateMap来执行此操作,因为映射规则到处都是相同的。

DTO的前缀为“ T _”。

// DTO 
public class T_ACCOUNT
{
    public int ID { get; set; }
    public int? PROFILE_ID { get; set; }
    public bool DELETED { get; set; }
    public string EMAIL { get; set; }
    public bool IS_EMAIL_CONFIRMED { get; set; }
    public DateTime TIME { get; set; }
}

// business model
public class Account
{
    public int Id { get; set; }
    public int? ProfileId { get; set; }
    public bool Deleted { get; set; }
    public string Email { get; set; }
    public bool IsEmailConfirmed { get; set; }
    public DateTime Time { get; set; }
}

所以我这样创建映射器。

var config = new MapperConfiguration(cfg =>
{
    cfg.AddProfile(new DtoToBusinessProfile());
});

IMapper mapper = new Mapper(config);

个人资料如下。

public class DtoToBusinessProfile : Profile
{
    public DtoToBusinessProfile()
    {
        // this should match mapping between "Account" and "T_ACCOUNT"
        AddConditionalObjectMapper()
            .Where((s, d) =>
            {
                return s.Name == d.Name.Substring(2).Pascalize();
            });

        // Now what?
    }
}

feature request起,我在Automapper github中创建了I could not get the INamingConvention interface to work

有人告诉我,使用ForAllMaps也可以实现我想要的功能,但是我不知道该怎么做。

1 个答案:

答案 0 :(得分:0)

在Automapper中找到了a bug,但还有两个映射器的有效解决方案。显然,LowerUnderscoreNamingConvention与大写属性也能很好地工作。

IMapper dtoToBusinessMapper = new MapperConfiguration(cfg =>
{
    cfg.AddConditionalObjectMapper()
       .Where((s, d) => s.Name == d.Name.Substring(2).Pascalize());
    cfg.SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
    cfg.DestinationMemberNamingConvention = new PascalCaseNamingConvention();
}).CreateMapper();

IMapper businessToDtoMapper = new MapperConfiguration(cfg =>
{
    cfg.AddConditionalObjectMapper()
       .Where((s, d) => s.Name == "T_" + d.Name.Underscore().ToUpperInvariant());
    cfg.SourceMemberNamingConvention = new PascalCaseNamingConvention();
    cfg.DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention(); 
}).CreateMapper();

T_ACCOUNT tableRow = new T_ACCOUNT()
{
    DELETED = 0,
    EMAIL = "asdf@asdf.cz",
    ID = 8,
    IS_EMAIL_CONFIRMED = 1,
    PROFILE_ID = 11,
    TIME = DateTime.Now
};

Account businessModel = dtoToBusinessMapper.Map<Account>(tableRow);
T_ACCOUNT backToDto = businessToDtoMapper.Map<T_ACCOUNT>(businessModel);