Сложная конфигурация 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();
}
}
}