Сложная конфигурация Automapper

Я сопоставляю существующую базу данных с DTO и снова использую Automapper (4.1.1), и я столкнулся с несколькими небольшими проблемами.

У меня есть (упрощенная) модель для таблицы базы данных:

public class USER_DETAILS
{
    [Key]
    public string UDT_LOGIN { get; set; }
    public string UDT_USER_NAME { get; set; }
    public string UDT_INITIALS { get; set; }
    public string UDT_USER_GROUP { get; set; }
    public decimal UDT_CLAIM_LIMIT { get; set; }
    public string UDT_CLAIM_CCY { get; set; }
}

и объект DTO:

public class User
{
    public string Login { get; set; }
    public string UserName { get; set; }
    public string Initials { get; set; }
    public string UserGroup { get; set; }
    public double ClaimLimit { get; set; }
    public string ClaimCurrency { get; set; }
}

Я создал профиль

public class FromProfile : Profile
{
    protected override void Configure()
    {
        this.RecognizePrefixes("UDT_");
        this.ReplaceMemberName("CCY", "Currency");
        this.SourceMemberNamingConvention = new UpperUnderscoreNamingConvention();
        this.DestinationMemberNamingConvention = new PascalCaseNamingConvention();
        this.CreateMap<decimal, double>().ConvertUsing((decimal src) => (double)src);

        this.CreateMap<USER_DETAILS, User>();
    }
}

Тем не менее, кажется, что Automapper не любит объединять столько параметров в конфигурации. Даже упрощая модели, я не могу получить

        this.RecognizePrefixes("UDT_");
        this.ReplaceMemberName("CCY", "Currency");

работать вместе, и пока

        this.CreateMap<decimal, double>().ConvertUsing((decimal src) => (double)src);

работает нормально с моделями в тесте, он не работает при использовании его с базой данных.

Есть ли способ заставить все это работать вместе, или я должен вернуться к использованию ForMember (). Я действительно надеялся, что смогу это сделать, так как в этой системе много таблиц, и я бы предпочел не делать каждую из них по отдельности.

1 ответ

Вам нужно будет расширить это для других типов, только протестированных со строками, у меня есть метод расширения, который выполняет всю работу и ищет несопоставленные свойства.

public class USER_DETAILS
{
    public string UDT_LOGIN { get; set; }
    public string UDT_USER_NAME { get; set; }
    public string UDT_INITIALS { get; set; }
    public string UDT_USER_GROUP { get; set; }
   // public decimal UDT_CLAIM_LIMIT { get; set; }
    public string UDT_CLAIM_CCY { get; set; }
}

public class User
{
    public string Login { get; set; }
    public string UserName { get; set; }
    public string Initials { get; set; }
    public string UserGroup { get; set; }
    //public double ClaimLimit { get; set; }
    public string ClaimCurrency { get; set; }
}

public static class AutoMapperExtensions
{
    public static IMappingExpression<TSource, TDestination>
        CustomPropertyMapper<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
    {
        var sourceType = typeof(TSource);
        var destinationType = typeof(TDestination);
        var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType == sourceType && x.DestinationType == destinationType);

        var properties = sourceType.GetProperties();
        foreach (var property in existingMaps.GetUnmappedPropertyNames())
        {
            var similarPropertyName =
                properties.FirstOrDefault(x => x.Name.Replace("_", "").Replace("UDT", "").ToLower().Contains(property.ToLower()));

            if(similarPropertyName == null)
                continue;

            var myPropInfo = sourceType.GetProperty(similarPropertyName.Name);
            expression.ForMember(property, opt => opt.MapFrom<string>(myPropInfo.Name));
        }
        return expression;
    }
}

class Program
{
    static void Main(string[] args)
    {
        InitializeAutomapper();

        var userDetails = new USER_DETAILS
        {
            UDT_LOGIN = "Labi-Login",
            UDT_USER_NAME = "Labi-UserName",
            UDT_INITIALS = "L"
        };

        var mapped = Mapper.Map<User>(userDetails);
    }

    static void InitializeAutomapper()
    {
        Mapper.CreateMap<USER_DETAILS, User>().CustomPropertyMapper();
    }
}

}

Другие вопросы по тегам