Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

511
Views
Mapeo personalizado con AutoMapper

Tengo dos objetos muy simples:

 public class CategoryDto { public string Id { get; set; } public string MyValueProperty { get; set; } } public class Category { public string Id { get; set; } [MapTo("MyValueProperty")] public string Key { get; set; } }

Al asignar una Category a un CategoryDto con AutoMapper, me gustaría el siguiente comportamiento:

Las propiedades deben mapearse como de costumbre, excepto aquellas que tienen el atributo MapTo . En este caso, tengo que leer el valor del Atributo para encontrar la propiedad de destino. El valor de la propiedad de origen se utiliza para encontrar el valor a inyectar en la propiedad de destino (con la ayuda de un diccionario). Un ejemplo siempre es mejor que 1000 palabras...

Ejemplo:

 Dictionary<string, string> keys = new Dictionary<string, string> { { "MyKey", "MyValue" } }; Category category = new Category(); category.Id = "3"; category.Key = "MyKey"; CategoryDto result = Map<Category, CategoryDto>(category); result.Id // Expected : "3" result.MyValueProperty // Expected : "MyValue"

La propiedad Key se asigna a MyValueProperty (a través del atributo MapTo ) y el valor asignado es "MyValue", porque el valor de la propiedad de origen es "MyKey", que se asigna (a través del diccionario) a "MyValue".

¿Es esto posible usando AutoMapper? Por supuesto, necesito una solución que funcione en todos los objetos, no solo en Category/CategoryDto.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Finalmente (después de tantas horas !!!!) encontré una solución. Comparto esto con la comunidad; espero que ayude a alguien mas...

Editar: tenga en cuenta que ahora es mucho más simple (AutoMapper 5.0+), puede hacer lo que respondí en esta publicación: ¿Cómo hacer que AutoMapper trunque cadenas de acuerdo con el atributo MaxLength?

 public static class Extensions { public static IMappingExpression<TSource, TDestination> MapTo<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression) { Type sourceType = typeof(TSource); Type destinationType = typeof(TDestination); TypeMap existingMaps = Mapper.GetAllTypeMaps().First(b => b.SourceType == sourceType && b.DestinationType == destinationType); string[] missingMappings = existingMaps.GetUnmappedPropertyNames(); if (missingMappings.Any()) { PropertyInfo[] sourceProperties = sourceType.GetProperties(); foreach (string property in missingMappings) { foreach (PropertyInfo propertyInfo in sourceProperties) { MapToAttribute attr = propertyInfo.GetCustomAttribute<MapToAttribute>(); if (attr != null && attr.Name == property) { expression.ForMember(property, opt => opt.ResolveUsing(new MyValueResolve(propertyInfo))); } } } } return expression; } } public class MyValueResolve : IValueResolver { private readonly PropertyInfo pInfo = null; public MyValueResolve(PropertyInfo pInfo) { this.pInfo = pInfo; } public ResolutionResult Resolve(ResolutionResult source) { string key = pInfo.GetValue(source.Value) as string; string value = dictonary[key]; return source.New(value); } }
over 4 years ago · Santiago Trujillo Report

0

Esto debería ser bastante sencillo usando una implementación de IValueResolver y el método ResolveUsing(). Básicamente, solo necesita tener un constructor para el resolutor que tome la información de la propiedad (o si quiere ser elegante, tome una expresión lambda y resuelva la información de la propiedad de manera similar a ¿Cómo obtener la PropertyInfo de una propiedad específica? . Aunque yo No lo he probado yo mismo, me imagino que lo siguiente funcionaría:

 public class PropertyBasedResolver : IValueResolver { public PropertyInfo Property { get; set; } public PropertyBasedResolver(PropertyInfo property) { this.Property = property; } public ResolutionResult Resolve(ResolutionResult source) { var result = GetValueFromKey(property, source.Value); // gets from some static cache or dictionary elsewhere in your code by reading the prop info and then using that to look up the value based on the key as appropriate return source.New(result) } }

Luego, para configurar esa asignación, debe hacer lo siguiente:

 AutoMapper.Mapper.CreateMap<Category, CategoryDto>() .ForMember( dest => dest.Value, opt => opt.ResolveUsing( src => new PropertyBasedResolver(typeof(Category.Key) as PropertyInfo).Resolve(src)));

Por supuesto, eso es un lamda bastante asqueroso y le sugiero que lo limpie haciendo que su resolución de propiedades determine la propiedad en el objeto de origen que debe mirar en función de la información del atributo/propiedad para que pueda pasar un nuevo PropertyBasedResolver limpio ( property) en ResolveUsing() pero espero que esto explique lo suficiente para ponerlo en el camino correcto.

over 4 years ago · Santiago Trujillo Report

0

Supongamos que tengo las siguientes clases

 public class foo { public string Value; } public class bar { public string Value1; public string Value2; }

Puede pasar una lambda a ResolveUsing:

 .ForMember(f => f.Value, o => o.ResolveUsing(b => { if (b.Value1.StartsWith("A"));) { return b.Value1; } return b.Value2; } ));
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!