corner - automapper c# example
Ignorar la asignaciĆ³n de una propiedad con Automapper (8)
Ahora hay (AutoMapper 2.0) un atributo IgnoreMap, que usaré en lugar de la sintaxis fluida, que es un poco pesado en mi humilde opinión.
Estoy usando Automapper y tengo el siguiente escenario: Class OrderModel tiene una propiedad llamada ''ProductName'' que no está en la base de datos. Entonces cuando trato de hacer el mapeo con:
Mapper.CreateMap<OrderModel, Orders>();
Genera una excepción:
"Las siguientes 1 propiedades en Project.ViewModels.OrderModel no están asignadas: ''ProductName''
He leído en el Wiki de AutoMapper para Proyecciones el caso opuesto (el atributo adicional está en el destino, no en la fuente que es realmente mi caso)
¿Cómo puedo evitar automapper para hacer el mapeo de esta propiedad?
Al asignar un modelo de vista a un modelo de dominio, puede ser mucho más sencillo validar simplemente la lista de miembros de origen en lugar de la lista de miembros de destino
Mapper.CreateMap<OrderModel, Orders>(MemberList.Source);
Ahora mi validación de mapeo no falla, requiriendo otro Ignore()
, cada vez que agrego una propiedad a mi clase de dominio.
Aprecié una extensión agregada por Steve Rukuts, así que decidí agregar un método de extensión más basado en su ejemplo. Espero que ayude a alguien
public static IMappingExpression<TSource, TDestination> Map<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> map,
Expression<Func<TSource, object>> src,
Expression<Func<TDestination, object>> dst)
{
map.ForMember(dst, opt => opt.MapFrom(src));
return map;
}
Uso:
Mapper.Initialize(cfg => cfg.CreateMap<UserModel, UserDto>()
.Map(src => src.FirstName + " " + src.LastName, dst => dst.UserName));
De Jimmy Bogard: CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());
Está en uno de los comentarios en su blog .
Hola a todos Por favor, use esto está funcionando bien ... para el mapeador automático, use múltiples .ForMember en C #
if (promotionCode.Any())
{
Mapper.Reset();
Mapper.CreateMap<PromotionCode, PromotionCodeEntity>().ForMember(d => d.serverTime, o => o.MapFrom(s => s.promotionCodeId == null ? "date" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", DateTime.UtcNow.AddHours(7.0))))
.ForMember(d => d.day, p => p.MapFrom(s => s.code != "" ? LeftTime(Convert.ToInt32(s.quantity), Convert.ToString(s.expiryDate), Convert.ToString(DateTime.UtcNow.AddHours(7.0))) : "Day"))
.ForMember(d => d.subCategoryname, o => o.MapFrom(s => s.subCategoryId == 0 ? "" : Convert.ToString(subCategory.Where(z => z.subCategoryId.Equals(s.subCategoryId)).FirstOrDefault().subCategoryName)))
.ForMember(d => d.optionalCategoryName, o => o.MapFrom(s => s.optCategoryId == 0 ? "" : Convert.ToString(optionalCategory.Where(z => z.optCategoryId.Equals(s.optCategoryId)).FirstOrDefault().optCategoryName)))
.ForMember(d => d.logoImg, o => o.MapFrom(s => s.vendorId == 0 ? "" : Convert.ToString(vendorImg.Where(z => z.vendorId.Equals(s.vendorId)).FirstOrDefault().logoImg)))
.ForMember(d => d.expiryDate, o => o.MapFrom(s => s.expiryDate == null ? "" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", s.expiryDate)));
var userPromotionModel = Mapper.Map<List<PromotionCode>, List<PromotionCodeEntity>>(promotionCode);
return userPromotionModel;
}
return null;
Puedes hacerlo:
conf.CreateMap<SourceType, DestinationType>()
.ForSourceMember(x => x.SourceProperty, y => y.Ignore());
Solo para cualquiera que intente hacer esto automáticamente, puede usar ese método de extensión para ignorar las propiedades no existentes en el tipo de destino:
public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof(TSource);
var destinationType = typeof(TDestination);
var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType)
&& x.DestinationType.Equals(destinationType));
foreach (var property in existingMaps.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
para ser utilizado de la siguiente manera:
Mapper.CreateMap<SourceType, DestinationType>().IgnoreAllNonExisting();
Gracias a Can Gencer por la punta :)
fuente: http://cangencer.wordpress.com/2011/06/08/auto-ignore-non-existing-properties-with-automapper/
Tal vez sea un poco perfeccionista; Realmente no me gusta la sintaxis de ForMember (..., x => x.Ignore ()). Es una cosita, pero me importa. Escribí este método de extensión para hacerlo un poco mejor:
public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> map,
Expression<Func<TDestination, object>> selector)
{
map.ForMember(selector, config => config.Ignore());
return map;
}
Puede ser utilizado como tal:
Mapper.CreateMap<JsonRecord, DatabaseRecord>()
.Ignore(record => record.Field)
.Ignore(record => record.AnotherField)
.Ignore(record => record.Etc);
También puedes reescribirlo para trabajar con params
, pero no me gusta el aspecto de un método con montones de lambdas.